Build Flappy Bird with React Native: Skia & Reanimated Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up noj developers welcome back to a new tutorial today I have prepared something exciting for you today we are actually going to build Flappy Bird in react native using uh skia gesture Handler and some Physics so this is a little and fun tutorial that is going to help you get started with a Rec native skia in Rec native um and yeah um let's let's get started because it's going to be fun let's run the [Music] intro so without wasting a lot of time here is the proof of concept but we're going to start everything from scratch and we're going to do it together uh for that we're going to of course use Expo for our rec native application and we are going to use Rec native skia because I've been wanting to use re native skia for a very long time but never found like the the right time for it so let's go ahead and open up a terminal and start by initializing a brand new project I'm going to do that with npx Expo not Expo but create uh Expo up at latest to take the latest version of Expo and let's go ahead and name it flappy flappy bird now uh Expo will download the the project we'll set set up a brand new uh project for us and we're going to be ready to to get started while this is happening let's go ahead and find the Shopify slra native skia um package shout out to Shopify and William uh for making this Library possible let's go ahead and open the documentation and if you're not familiar with ragni skia uh this is a way to use the skia graphics Library and the SC Graphics library is actually powering very some of the most powerful engines out there for example it's powering Google Chrome Chrome OS Android uh it's powering flatter and uh a lot more um browsers so the way it works is basically um it is rendering pixels on the screen in a very easy way to explain it for mobile applications uh if we talk about like flatter versus native in a lot of cases we don't want to treat our native application as a game let's say and basically render every pixels ourself that's how flatter is uh is rendering the user interface while re native is actually using native components like buttons text and so on this is very good uh in terms of using these kind of uh Native components when rendering user interfaces but for very specific use cases where we need control over the pixels on our uh on our screen rag native skia is here to help us do just that so we get a blank canvas and on that canvas we can paint we can animate we can do everything with those pixels that we uh we can imagine so this opens up the doors to a lot of interesting projects a lot of things that were previously not possible uh specifically around I don't know like uh game charts uh working with um with graphics and actually I already have a couple of ideas of some kind of um creative programming projects where we could render some some interesting stuff we could play with maps and so on but um yeah let's see our Expo project is set up and installed let's go ahead and open it in Visual Studio code here it is come on and after we have it here I'm going to run this application uh to to to have to to see it on the device so let's go ahead and start with npm start this will start the development server I'm going to close expoo um and I'm going to probably go ahead and close my previous one yeah let me close the previous one I don't need it anymore and here run again npm start hello everyone who is joining us live how are you doing guys by the way I forgot to mention stay tuned till the end of this video because at the end we're going to do the giveaway that we have promised to do for the uh for the survey that we were running so we're going to do that in in today's video and we will announce it on our social medias so let's go ahead and we see here the terminal let's run the application and at the beginning if we open up. GS we should simply see a text rendered on the screen did I do something wrong no here it is the text is rendered on the screen my vs code is complaining about uh about V so I will simply press on let me see if you can also see it here I'll simply press on this icon and press configure GS config this will create a new file GS config and here under GSX I'm going to do react native GSX now everything is working fine and we are ready to to start working if I'm going to go ahead and change this text to hello there it's going to automatically be uh changed on our screen as well so we have a blank application a blank react native application let's go ahead and set up and install react native skia let's open the documentation and in the installation all we have to do is basically take the name of this package at Shopify /ra nativ skia open up our terminal open a new terminal and do npx Expo install and V the name at Shopify / reac native skia and because uh Rec native skia is built in or part of the Expo go we don't have to pre-build anything we can continue using expoo application to test our application being it on our simulator or by simply scanning this QR code with our physical device using expoo on our iOS or Android devices um so now that we installed it I think we can go ahead and do copy paste the hello world and see if it works so I'm going to copy paste let's copy paste everything from here go back to our application for in up. Gs let's remove everything and paste the hello world provided by R native skia if I do that I should already see without doing anything more I should already see the three circles rendered on the screen and as you can see they also have some kind of a blend mode where the color is blending between each other so perfect that means that our um rack native skia was installed correctly and we can render a canvas here if I'm going to go ahead and do a background color red here for the canvas we see that the canvas is uh has this width and height um what I want to do is a for a game usually the canvas is full screen if you are integrating R native skia in in a different application where you need the canvas to be a small UI component you can do that uh perfectly fine for example in one of my other applications I'm using recognitive scale for graphs so the graph is just one simple component of my whole application but because today we're going to build a game we're going to build Flappy Bird uh our canvas should be the whole screen so let me go ahead and import uh the hook use Dimension use Windows Dimensions from react native and I can also remove a import react we don't need that anymore and I'm going to take the width and the height from the use window Dimension so I'm going to remove them from here and let's do const equal use window dimensions and let's take WID and height from this value now the width and the height is the sizes of the screen and it will also automatically resize when we um when we change orientation because it's a hook so it will automatically update as the window sizes changes and I think if I'm not mistaken maybe it's not out of a box if yeah we would have to set up the web maybe we can do it at the end to check it also on the web but for now I'm going to leave it like this so what do we have now we have a canvas that expands our on the whole screen and inside this canvas we can draw stuff at the moment it's drawing this uh circles uh I can probably go ahead and get rid of them because in the next step you see the background color doesn't Auto refresh I should do reload by focusing on the simulator and doing RR or by simply pressing R in my terminal and now it's re the the styles are reset as well yeah uh I removed everything that's rendering there because in the Flappy Bird I'd like to start by rendering a background image for the assets that we're going to use I found a GitHub uh repository I search Flappy Bird uh assets and there is this GitHub repository with the Sprites with all the assets that we would need today so let's go ahead and press uh download zip and some where there give me just one second to find it properly yeah and after you unzip and open this one here you will find the following assets one of them is the Sprites folder that contains Sprites or images that we will need so let's drag and drop the Sprites inside the assets so now our assets folder in our project contains the Sprites and one of the Sprites that we are interested in is in this background day or even background night PNG so let's go ahead and check the documentation how we can render a image in a Rec native skia I'm going to go to the image uh documentation and we see that first of all we need to load the image uh using the use image cook and after that using the image component we can render it so that means that first we have to import some of the stuff from react native skia I don't need the circle and the group at this moment I'm going to remove them uh instead I need the use image hook to load the image and the image component to render it now at the top of application let's go ahead and load the background image using the use image hook and here we're going to use very require and provide the relative puff to our Sprite to our image itself so because we are in upgs we need to go inside assets so from this directory go inside assets then go inside Sprites then take the background background- day.png double check to have proper name in here and after we have this background image loaded we can go Ahad ahead and try rendering it inside the canvas using the image component so image image background we already see it that's perfectly uh that's perfect now we can give this image the the what is our required property is it the re is declar here let's check if I can do fet uh cover the whole Space if that would work no because it also needs the WID so the wi in our case should match the wi of the screen so let's take wi equal wi um and it still doesn't work and if I do height equal height now it works why with only wi it didn't work that's a bit strange but anyway if I have both WID and height which I should anyway I should uh it renders full screen we can also adjust how we want to fit the image inside the container that we Define with this size uh and I want it to cover in order to take the whole Space because if I do contain here which I think is the default one we're going to see that the aspect ratio of my phone and the aspect ratio of the image is different so I have a white bars here so that's why I use the cover style here perfect so now that we have we have the background rendered on the screen uh perfect now we have a background then we need to render what we need to render the bird itself let's go ahead and import it so first of all we're going to need to import the image of a bird using use image and then require and we need the puff to the image so let's take it as assets Sprites and the Sprite is called I think yellow bird or red which is the standard one red or yellow I don't know let's take the Yellowbird upfap PNG so the name make sure to take the name correctly and let's go ahead and render it on the screen I'm going to render the image uh for the image I'm going to render bird it should be here at the top left of the screen we can adjust where we want to render on the canvas by positioning the X or the Y let's say to be middle of a screen so the middle of a screen would be high ided by two now if I reload it doesn't show up there should I also give an x y and x and it doesn't want to move uh well I think it it wants the other like WID and height so let me check what's the width I think the WID of 52 or something like that and the height of that image I can check that by looking revealing in finder scrolling it's 32 by 24 so it's 32 with by 24 height okay so now that I provided the props that it needs uh I would expect actually for it to to take let's say default one so if I don't provide height I would expect it to take height zero but if I don't provide the height it doesn't even take the weave for the X and Y so I need to provide all of them in order for it to properly position on the screen and for this one the fit should be probably contained because I want the whole bird to be uh visible on the screen and for example I can also make it a little bit bigger by increasing the size twice so from 32 maybe we should go 64 and height 48 yeah let's see let's see so the X in our case is 120 we hardcoded this one if we want it in the middle of a screen we should probably do wave divided by two divided by two which actually is not actually the middle of the screen because here we are specifying the X and Y of the top left corner of this image so if the image would be very large you're going to see that this we are positioning in the center the middle of of a bird so probably a better way like if you really want to center it is high ided by two minus half of a WID of a bird and the WID of a bird is 64 so minus 32 and here no no I mean height height is 48 so minus 24 and minus half of the we 32 so now it's exactly in the center and again I'm not sure if flppy bear should be in the center on the x axis so I should probably do with divided by three to move it a little bit to the left or even four just for us to see like what's what's coming in front of us what do you say I think that that makes a lot more sense and for the why I don't think we need to over complicate it because the Y is going to be dynamic because we will want to move a bird up and down okay so now we have a background we have a bird hello everyone in the live chat uh Thiago hello Go full stack from us skia uh Elite coder hello how are you doing guys gelio khed all right guys so um now we have the bird on the screen probably the next step is going to be to add the how we called the pipes right the green pipes so the green pipe pipe green.png let's go ahead and load it so let's go ahead and start by doing const pipe equal use image and here I'm going to import it with require from assets Sprite and Van the name of the Sprite I think is green or pipe D green PNG so pip Das green.png let's go ahead and render it so maybe I should add some comments bird uh background and the pipes should be rendered before before the bird because they are kind of part of the background right so let's do pipes here so I'm going to render the image of our pipe let's see it not spring but Sprite come on so we see a Sprite rendered top left corner if I want to render it at the bottom what should we do we should do hey render it the Y position should be equal to the height of the screen the x is going to be zero so far then we need the width and the height right so let's double check the width and height of these red and green pipes I'm going to open this image here and I'm going to check that the width is 52 the height is 320 52 52 320 but the problem is that moving the Y to the bottom there moved it too much we need to move it by height minus the the height of the screen minus the height of a pipe so the height of a pipe is 320 so if I do minus 320 here I should have exactly what I want but again I think I'm uh if I zoomed in in twice my birdie think I should zoom in twice or make twice as large my pipes so I think I should do 104 by 600 40 and the height if I do 320 that's okay if I do 640 that's going to be the bottom is going to touch my bottom of the screen which I don't really want I will be able to move it up and down like this now I should do the same for the second one maybe for the X I can do screen with divided by two to have it in the center we'll see this is also going to to to change now I need the second pipe at the top so the second pipe at the top like this but in this case but why is going to be zero maybe even minus 320 just like this to to move it a little bit up the screen over the screen and everything else will probably be the same right yep oh now the challenge is to the challenge is going to be to um revert the the image you would be able to do that directly in skia using a group and some Transformations but in order to not over complicate it right now because I was trying and it's a bit tricky to with to work with Origins and so one I would go ahead and simply open my Sprite in finder I would go ahead I would find the pipe green I will duplicate the pipe green create a copy with it I will call it pipe green dashtop I would open it up and simply do boom boom save and just like that I simply have a image that is actually um mirrored and yes I would have to load two different images it's not very pipe and pipe top pipe green dashtop it's not very efficient but it's fast and I like that so the image here is going to be pipe top and maybe I should first render the pipe top and then the pipe which maybe should be pipe bottom like that and just like that we have two pipes uh exactly how we wanted them to look H okay now that we are here on the pipes let me let me declare the let me fix this red warnings because you might think that you have an error but this is not an error this is basically typescript not knowing that hey there is a PNG type of file so let me quickly search on stack Overflow how to fix it I just need to declare a typescript declaration file PNG so I would have to Simply create somewhere here types. d. TS actually I'm not even using typescript I'm using JavaScript but anyway I declare that there is a file type with PNG and now my error disappeared okay okay okay I don't need this R any longer so I can have it like this and yes as I saying we have these uh pipes I'm thinking about um way to be able to move both of the pipes up and down depending on a constant or depending on a on a value uh and I would do it actually right now so let's have a value of uh pip offset which is going to be equal to zero initially so if pipe offset is zero I want the Gap to be perfectly centered so how I'm going to do it is going to be pipe offset minus 320 minus pipe offset or pipe offset minus 300 let's write pipe offset - 320 and here for the Y is going to be height - 320 well let me move this P set by 100 and see what's happening so if I if it's 100 it's going to go down if it's minus 100 it's going to go up now it should also affect the Y for the second pipe should I also do minus pipe offset because it's in the other direction here it's with plus here it's with minus and now if I'm going to have 100 will both of them move in the same direction no that's what I didn't want to happen in this situation they're simply closing up uh so probably I should do plus pipe offset yes now if it's minus 100 we're moving both to the bottom one minus 100 both to the top okay so I'm going to leave it with pipe offset zero we have it in the center okay all right so uh we have a pipes we have a bird web background I think what we are actually missing is the ground and if we look in the Assets in the prit I think they also have this base base.png let's go ahead and finally render a base uh const base equal use image require assets Sprite base PNG and let's go ahead and probably it's we'll see because if we render it before the pipes the pipes will be on top I think so image image equal base I want the wave of this image to be the width of the screen and the height I don't know 300 or something like that maybe 300 is even too much 200 100 yeah maybe 100 is okay but the Y value should be the screen height I want to move it to the bottom but I will substract from there the half of the height of a base so minus 50 and X is going to be zero of course now the base is somewhere there and by simply doing a fit cover it should cover the the available space and as I said this one should move to below the pipes so that the pipe is behind the ground and maybe the height should be 150 and here 75 something like this yeah probably that's better okay that's good that's looking like Floppy Bird already uh I'm going to go ahead and actually do a g status G add G commit set up the base uh assets of Flappy Bird because we have a base the the base thing like the fundamentals now the next step is going to be to start moving things around to start animating things and this is where the fun part begins we're going to move things around using rack native reanimated if you go to R native skia add the animations we will see that Rec native ski offers first class integration with reanimated so that means that it's optimized and it actually we can pass to retive skia components we can pass animated views and it will work out of a box without us having to basically create some adapters for it so let's go ahead and open ranimated in a new tab and go ahead and install it in our application I think with ranimated we don't need a lot of things we will just do npx Expo install rack native ranimated npx Expo install R Na reanimated and we actually yeah we have to add the plugin under the plugins in the B.C config so back in our code uh in our bable config file after the presets let's add the plugins uh the plugins which is an array we are going to remove these fre dots and if you have other plugins simply add rect native ranimated at the bottom of it list if not just simply add plugins array with ranimated v here now we would have to go back where our application is running stop it and uh start it with dh- space-- clear to clear the cache and make sure that everything is working correctly let's go ahead and open it in iOS reanimated is also included in Expo go so we don't have to pre-build anything we can continue using Expo go and we're going to continue using it by the end of the tutorial everything is still working fine which which I like so let's go ahead and do what we don't have to do anything else we can already start animating things so um we're going to start with animating the pipes and here let me explain a little bit uh how a lot of game games are working because when we think about the movement of flppy bird uh let's Flappy online we think that actually we are we as a as a bird are moving on the uh on a map right we are the the the X position of a bird is moving and everything else remains static well you can accomplish that but that would be a bit more challenging because first of all You' have to move the bird and you'll also have to think about the camera and move the camera around but if you switch like how you think about it and consider the bird static on the A and instead the pipes and everything else moving towards the bird then it's going to be much more easier because the bird is going to be static the camera is going to be static and everything is going to Simply move towards the bird and this gives you the impression that the bird is moving when in fact everything else is moving so what do I mean by that I mean that let's have let's have a shared value uh x const x use shared value from react native ranimated I'm going to start with zero and this x you is use used Share value a used Share value is driving our animations um it's available on our UI thread and based on it we can animate or move positions of things on the UI thread so what I can do here is H probably start by assigning the x of our pipes to be equal to the x. value and here x dot X do value let's initialize the uh the X with the weave of a screen if I do with here and reload the application we will not see the pipes because they are basically outside the the screen if I'm going to do with minus 50 you're going to see just a little bit of the of the pipes perfect um now what I want to do is I want to animate this x value or basically the the x value of pipes to move towards the the left of the screen towards the bird to do that I'm going to start this animation in a use effect basically when the component mounts or when the game starts so what I'm going to do is I'm going to assign y x value instead of saying that hey you should move towards zero and zero is basically the other half of the screen I will not going to do that because that will simply move it at the same time like in the same frame I'll say move towards zero but over a small period of time and I can do that with a hook with timing and this is already an animation so the with timing hook I'm going to import from react native reanimated and if I say like with timing move towards zero and refresh this one a doesn't work why I don't know with timing x value did I forget to set something up yeah I think so wait a second reanimated something uh something doesn't click in my brain what happens here let's try to clear the server start it again hello that's very weird with x value with timing zero with timing from reanimated can say over what period of time for example duration one second but that shouldn't affect it yep that shouldn't I'm a bit uh confused let me double check with timing X do value plugins in bble config used shared value anyone sees what I'm doing wrong let me check check the reanimated version don't think it should be that reanimated reanimate 3.6.2 and in like today I was testing it with 3.6.2 maybe but also no let's try I don't know um let's do on press let me even check if there is a one press I think it it should would be hello it's not there on touch hello hello so if I do here x. value equal with timing maybe the image is not animated the the thing is that we don't we don't have to transform this to animated components because it supports sending animated values should I send simply the ax yep yep yep boy I see so the problem I'm going to go back thank you for giving me a hint um and no it we shouldn't do animated. image this image is coming from retive skia and I think most of rective skia components they can receive animation objects the problem is that I was sending directly the value when I should actually send a shared value so instead of X do value I should send the whole X which is a shared value and the same one from this one now as you can see our uh animation from left to right is working when we restart the screen the the type of uh so the weave timing hook will allow us to uh move toward a value towards a direction in this case we are moving towards minus to towards zero I think I would like to move it towards minus 100 to move it behind the screen even minus 200 probably to move it all the way behind the screens but the over a period of time so now we are saying that we want to move it over 1 second if I'm going to do it over three seconds it's going to slow it down because it's going to run the same animation but U throughout 3 seconds The Weave timing can also have the easing method like how the timing affects the value as you can see by default it starts slow it picks up speed and then it slows down at the end this is um this is not a linear animation because it doesn't move with the same speed throughout it but we can change that by providing to the option here eing and we can import different easing functions from R animated and one of them that I want here is eing do linear the linear eing will basically move animation with the same speed from the beginning to the end in a straight line so now I can go back here to minus 150 and as you can see from the beginning it starts and it looks like our bird is moving I'm not sure what to do with the ground because I should also somehow uh move the ground uh but in a way for it not to maybe I can have like two grounds pipe pipe this is the base for the for the X should I do X here it will also move somehow like this and I could simply have two grounds uh this is the base I can have two of them I can do X here I would have to do a how is it called um derived value so actually I'm going to not animate the ground for now just to to keep it simpler for us not to over complicate the code I'm going to only move the pipes so now the pipes are moving perfect what I can do is uh when they reach the end of Animation I can move them back where they started to do that that basically means that we have to run two two animations so first things first to run two animations we can sequence them one after another with another uh modifier with sequence so if I'm going to put here with sequence and then inside the wave sequence we can pass different uh modifiers they will run one after another so for example after we go to the left let's reset also using with timing back to the initial position with let's see how this will look I have to put here a comma if I restart uh come on come on okay then it will go back there but it also goes there with timing animations which we don't really want I think we can set the duration to zero to set that hey just respond there without moving towards that direction and after we are there what we can do is we can repeat the same animations animation once again or maybe we don't even have to repeat it once again what we should actually do is we should repeat the whole sequence infinite number of times so you start from the right of a screen you go to the left of a screen over a period of 3 seconds then you respond back to the right of the screen come on why reload let me open it up flippy so you go to the left then you respond there and what I want to do is to start over uh again to start this sequence again for that we have another modifier which is called with repeat and we can put any kind of animations like with sequence with timing inside a wh repeat so I want to repeat the sequence that's why I'm going to put it with repeat inside the with repeat we have a sequence at the end we end it and here you need to specify as the second parameter how many times do we want to repeat it if I provide minus one is going to repeat it infinite number of times so let's see what's happening okay goes there the next one the next one and the next one perfect amazing so just like that we have our map moving uh Advent we're going to see maybe we can do two multiple um sets of pipes so that we don't have empty screens uh without any pipes so we're going to have like two sets of pipes going and then responding and so on but for now that's uh that's good enough for us so let's go ahead and do uh get add get commit minus M um moving pipes perfect now that we have our pipes moving I think the next step for us is going to be to start moving our little bird uh so moving our bird for that we are going to have first of all the bird is not going to move on the x axis we already figure that out because the bird always stays in the same position we will only move it up and down so let's go ahead and Define here a bird y as a shared value a shared one because we will have to animate it initially is going to be probably height divided by two let's take this bird Y and go ahead and add it to our bird image for the Y instead of this value I'm going to give it bird y shared value if I restart everything is back there um the first time I was implementing this uh the physics of the bird I was using the same um Animation Way like with timing and with repeat and so on for example what we can do to simulate the bird Falling Down is we can say that the bird y do value is going to go uh using the timing mechanism is going to go to the bottom of the screen which is probably height and is going to fall over a duration of let's say of 1 second so if I have that my bird will fall down if I restart is going to fall and this way it's perfectly fine uh I made it work king um you can also change the bird y position when we tap on the screen to move it up but at the end like the physics was not very realistic so the next step was okay if the physics is not very realistic let's try to actually simulate the physics here because it's not that complicated there is not a lot of forces uh that are applied to our little bird so let's give it a try and use real physics and real some some some real physics formulas to move our little bird first of all let's uh figure what are going to be the physics formulas or forces that are going to uh apply to our bird first of all we have the bird somewhere here starting at the top and the bird is going to have um velocity which is the speed of how fast it's falling down theity let me do Xcel so initially the bird starts with a velocity zero the bird will also have the let's say with velocity uh the bird is falling with 10 m/ second is going to have a initially a static velocity so that means that we can calculate the position of a bird uh based on knowing its velocity so after 1 second based on this formula we know that the bird fell down by 1 meter so this is going to be probably a one or 10 m right because if it's falling down with 10 m a second after a second the bird probably fell down 10 m then after 2 seconds it's going to fall down 10 more M so that's how we can calculate the position of a bird at any point in time let's go ahead and implement this one and then we're going to come back and think about how does gravity apply to all of this so as we said the Velocity in this scenario is static and the position is going to move based on the velocity okay let's start by defining the const bird y velocity as I don't know 10 m per second we're going to figure out like all of these constants but for now 10 is going to be enough now at every FR refresh or at every time we redraw our frame on the screen we want to update the Y position based on the velocity there is a hook called use frame callback from reanimated it's imported here use frame call back from reanimated and this hook frame or let's do info and basically this Hook is called on every frame render it's also having information about the frame that is current currently rendering so let me refresh and check the console log if I'm going to stop at one point we see that this function is called very often and in fact it's being called 60 times every second because we have 60 frames per second and we also have this value come on let me stop it for a second just not to generate more stop it yeah so at every frame we have this value times since previous frame which indicates how much time did it pass since the previous frame this is very important for creating smooth animations because we cannot be sure that every frame takes the same amount of time to draw so what that means is that in fact we're not going to check the position after 1 second in fact we're going to check the position after after 100 m milliseconds we're going to calculate it based on the formula then we're going to check it after 200 milliseconds 300 milliseconds and so one we're going to check it a lot of time update the position smoothly until we get to to to this position so what I mean is that we need this time since previous frame to know how far should we move our bird let's take that time since previous frame as the Delta time DT now we have a initial position of a bird that we want to update so bird. y.v value is going to be that uh is going to be bird. y.v Value Plus because we are adding to the position to the current position we are adding the velocity multiplied by the Delta time so distance travel is equal is equal to speed multipli by the time but this Delta time sometimes can be null so we can check at the first draw or the first frame the Delta time is going to be null so I can check if it's null here I will return I will not do anything then I'm going to Simply update the Y position of a bird based on the velocity let's start it again no let's start it again and see what's happening okay our bird Fells down very very very very fast we can decrease the amount of of how fast it falls down by dividing it by 1,000 because the Delta time is in milliseconds and simply dividing it by 1,000 means that we are calculating velocity in seconds so that's that's better now we see that our bird is falling down a bit slower than we expect but it's falling down and velocity or the speed of how fast it FS falls down is constant because that's our initial step we have constant velocity every second it falls down 10 m you can by simply increasing this velocity here to 20 for example you're going to double the the speed if you increase it to 30 again if you do uh 70 is going fall a bit faster so this velocity helps us manage the speed of how fast the the the bird is falling well this is nice but in real life objects do not fall with a constant velocity objects start falling slow and the more they travel they increase their speed of falling until the it doesn't increase infinitely of course because there is drag but if we ignore the drag of the air the object will increase its speed uh as it falls down and that's because the gravity is pulling the object towards it I think I have here a small animation of demonstrating this so if we throw a ball up initially it's going to have a fast speed and it's slowly going to slow down until it reaches the velocity of 0 m/s at the top so at one point it stays static there then as it falls down it increases the speed 10 to 14 to 17 and when we it reaches us it's going to have a 20 m per second that because the velocity is changing uh and it's changing because of the acceleration where in this case gravity gravity serves as the acceleration of our object the gravity is the constant part now but the velocity changes let's see how that will affect our drawing here now I'm going to have a velocity here but I'm also going to have the acceleration let me do acceleration at the top because it's going to be static it's not going to to change so the acceleration of the earth is 9.8 something so I'm going to consider it 10 m/ second at Power of Two which means that acceleration or like the gravity will change the speed of Falling by 10 m/ second and every single second what does that mean that means that initially the object let's consider that it has velocity zero or let's consider it has velocity 10 so after 1 second it will travel here but during this one second it didn't only change the position it only change its velocity so now it has a new velocity because acceleration was apply apply to the current velocity so it changed from 10 m/s now it's falling with 20 m/s that means that the next state is not going to be here but it's going to be 20 M from here 20 M from here and in this case the velocity already will be 30 m per second and the next one even further so that means that as the object fall the speed of it falling increases let's do that in our code as we see the velocity is already not a static thing is going to be a shared value so let's do use shared value because we are going to change the velocity let's start with 100 here is going to be bird y velocity dot value now it's working the same but we're going to introduce the acceleration acceleration I'm going to do it at the top as a constant uh because let's do it as gravity because it's not going to change gravity never changes so let's use it as 10 9.8 if you want to be more precise so now the thing is that the position of our bird is going to depend only on velocity so I'm going to leave this one as it is because here here we are changing the position based on the velocity the only thing that I have to do is I have to do one more thing every frame I have to increase the velocity based on the gravity so the bird velocity do value is going to be equal to bird bird y velocity dot Value Plus is going to increase based on the gravity multiply by the Delta time because we want to take into consideration how um how much should we move in that direction and probably we should also divide it by 1,000 because the Delta time is in milliseconds and we probably want to work with seconds so now if I change it like this as our bird is falling is going to start falling faster I'm going to start the position of a bird from the top to have a little bit more time for us to see and at the top it falls down slowly now it falls down faster faster and faster and faster maybe you don't see it visually uh I can increase the gravity to 50 that means that the Earth is pulling faster and the objects will speed up faster I can do it even more 500 probably is going to be too much let's try yeah but it's visible at least so at the top it's slow and as it moves down it increases the speed of its falling we can also see that by simply doing console log velocity bird y velocity if I open here bird y velocity dot value so initially the velocity is 100 200 700 and it increases until yeah forever basically now okay so that's the very simple physics that is being applied to our bird the good thing is that now that we have and we know the velocity and so one throwing or our interaction with a bird is going to look very similar to the interaction of this person with a ball we are simply going to give initially a push to the bird where we're going to change the velocity of a bird in the opposite direction and then let the gravity do its work let the gravity stop it slowly at the top and move it slowly back down so this will give us a very natural interaction with a bird to do that let's go ahead and for example on the conas where is on touch and what I can do on touch is I can set the as I said I'll give a velocity uh opposite to the gravity so if the gravity is moving down I'll give it a minus velocity to move it up so bur velocity equal minus minus 100 let's see how it works so I will refresh and let's see if I press as you can see when I press I give this bird a velocity upwards and if I want to give it more push upwards I can increase like how much I change the velocity to When We Touch the canvas so when I touch it moves up a bit more and as you can see like the the gravity takes over like the gravity slowly slows it down and starts moving it faster down perfect the problem with this right here with the on touch is I don't know if you can see but when I press the background moves a bit slower which means that we have some frame drops you see that there is a stutter in the background movement that means that we have some frame drops uh and I can confirm that by opening the uh uh performance Monitor and as we can see whenever I don't touch a screen the UI and the GS thread are both running at 60 frames a second when I start pressing and if I press very very often the UI frame drops to 20 frames per second which is not good which means that our animation will start looking clunky as you can see here and um I'm not sure why this is happening uh maybe I have to memorize this function maybe the function is recreated every time but I think that a better approach to this is going to be to start using gesture Handler library to manage gestures and Rec native skia works out of a box with gesture Handler so let's go ahead and set install gesture Handler by running npx XO install react native gesture Handler in our project npx XO install R native gesture Handler okay if I look here the next step is going to be to uh wrap everything in this gesture Handler root view so let's take this gesture Handler root View and wrap it around our canvas when we return from our up compon component I'm going to wrap it around the root View and I should make sure to import this from R native gesture Handler at the top that will only add that gesture Handler now we also need to add the gesture detector so that one is going to be gesture detector which is a component that is being render and then detect gestures and we're going to also import the the the gesture itself that is going to allow us to create like the Handler so what I'm going to do is first somewhere after this use effect uh I'm going to do const gesture equal gesture Dot and here are a lot of gestures like pen pinch um swipe and so on what I'm interested in a very simple tap gesture and then I can provide functions to respond to different to the tap event at different point in time for example the on start is going to be a function that is going to be called whenever the gesture understand that it's a tap event so I can s console log tap now this gesture we need to Simply send it to a gesture detector that I'm going to use by simply wrapping around the whole canvas gesture detector I'm going to close this after the canvas ends so that our whole canvas detects gestures and I need to send here the gesture that we Define at the top now if I open it up here and if I comment out the on touch event from the canvas itself what we should see reload come on so if I press we see tap tap tap tap tap and our UI fret doesn't even Flinch like it remains stady at 60 um 60 frames a second and also the RAM usage stays constant that's perfect so let's move this bird velocity change inside the tap event and I will remove it from the canvas all together now if I start tapping we see that it works I think the gravity should be higher to start moving faster um now now I'm going to uh as we have the whole uh what do we have here bird physics now that we have these bird physics I'll try to improve a little bit the numbers in order to make it more realistic or more or closer to the real Flappy Bird because right now it moves really slow what I want to do is probably I will increase the gravity I'll start by increasing the gravity to uh 900 let's see what that will look like and probably the bird should jump higher a bit that means that I will increase the velocity that it gives like to 500 basically increasing both numbers to make it move faster to the top and faster to the bottom let's try 1,000 gravity what do you think I already have fun playing it yeah I think this looks kind of good in terms of physics okay that's that's good I'm going to leave it like this so gravity 1,000 and the let's say the jump const jump is going to be minus 500 so with jump let's do jump underscore Force jump Force we're going to use it here instead of using where I can yeah it's okay like this so that I can adjust this values right away from here perfect and the initial bird velocity probably can be zero and the bird y let's start somewhere at height divided by three like a bit to the top but not like completely at the top of the screen yeah that looks good so no matter how much the ram is at 162 megabytes UI and J Fred both are at 60 frames perfect looks good I think these values are good what a great explanation thank you thank you very much uh it's uh I I have a bit of experience with game development even though it was very much like very a long time ago that's what I wanted to see uh but yeah I was is working a bit as a game developer but I forgot everything so like this is probably the maximum math and physics that I remember like velocity and acceleration but I would I would like to to get back to it to maybe do some more interesting projects with with this kind of real life physics would would be like interesting challenge would you be interested in uh in having more projects like this covering like some Physics where maybe we can build some games some uh simulations but but anyway um so what would be the next step so we move a pice we move a bird uh keeping track of a score should we try that keeping track of the score actually before keeping track of a score uh I want to rotate a little bit our bird based on the velocity that it has so if it moves up I want the bird to to look up if it falls down I want the bird to look down so that means that I'll have to provide our bird a transformation right but I cannot add Styles here can I I don't think I can for example yeah I don't think F stroke image image is a skia skia image props I don't think I can do that so that means that probably I'm going to have to add it inside a group group I will have to put the image of a bird inside a group because a group can now have style right I will uh I will go ahead and comment out the use frame call back for a second just for me to to see the group style how do you apply transforms uh in R native skia image transforms Transformations transformation property this is on a group yep okay so it's not style but I can transform a group so I can do here transform and the transformation is an array and I can do rotate math. P not sure what happened but if I do rotate zero where will you be you're going to be there okay I think I might understand why because yeah at the moment our group if I would be able to do a background color here can I group color light blue will it show me how can I see the the group itself F should I do a fill yeah as you can see our group basically expands the whole screen what I have to do probably is going to be to say that the Y and X will not be on the image but on the group itself to move the group around the width and the height as well there no you don't want that group what I can do is I can simply change the origin to set the origin of a group like to leave it like this but to change the origin to the position of the bird because the position of a bird is let's see origin of a group where do you set it X and Y so if I will simply do group origin x uh with divided by four because that's the X position of our bird and the Y position to be bird Y and remove everything else of course bird y. value now if I'm going to start rotating will it rotate around itself yeah I see what it does uh maybe not around itself but around the corner but it's good because I can do from Z minus Z TR 0.8 which is going to be looking upwards to 0.8 so does this actually as you can see this thing is moving around um the top left corner of the of a bird I will increase the size of it so that you can see better so as you can see it moves around this top right corner if I want to move it exactly based on the center I'm going to have to add the size of the bird to this origin so X is going to be wave divided by four four but also plus this 64 let me do it like this plus not 64 but half of it so plus 32 and here bird y + 24 24 now it should be from the center 0.5 Z yes as you can see it doesn't move uh when rotating it rotates around its exact center perfect so now that means that this transform should be based on the velocity of the based on the velocity of the bird uh let's see if I would send here a shared value like velocity bird velocity do value or even bird velocity it's not going to work right dot value it still doesn't work maybe it's going to work velocity anyway um what I wanted to do actually is to say that based on the bird velocity we are going to calculate con at deriv Value bird how is it called rotation this is going to be a derived value because we derived it from the bird bir velocity we calculate in this function so let's return bird velocity do value so let's take bird rotation give it to our bird it doesn't work it needs dot value which makes me think that it's not going to work and if I change this use frame call back yeah it doesn't update but if we calculate the whole transform in that uh thing and call this one bird transform and we return here the whole thing and give it to the group to the whole transform now it works something is happening something is happening oh let's go let's let go I'm not sure what's happening but it looks so fun oh and as as I jump it comes back now I I know what's happening what's happening is that the rotation should not be the value of a velocity but should be a should be calculated based on the velocity so what I'm going to do I'm going to use from gesture Handler the interpolate function not from Handler from reanimated I'm going to import the interpolate and the rotation we are going to interpolate the value of the bird velocity and basically we are mapping a value from um from a range to another range so when the bird velocity is the velocity it goes from -500 to 500 so let's do if when it's minus 500 goes to 500 then the rotation when it's minus 500 is going to be I know 0.5 and V way is 0 minus 0.5 I don't know which one is which so maybe it's going to be reversed minus now let's open Expo again oh it looks like it's oh boy so funny and that's because of my um that's definitely because of a warigin because the warigin uh you see it has this uh shared value and we know that sending like the full origin should be if we want it to be animated we should send a whole shared value not DOT value so let's take this origin from here and add it also as a derived value const bird origin equal use derived value and we're going to return here this object yes and now we take bird origin and we send it as a shared value to the origin of a group now if I comment out the physics now it [Music] works that's so cool what you can do like with a interpolation is to also clamp it uh I guess type clamp how to clamp it interpolate clamp uh because I don't want the rotation to even grow above the values that I already sent and it's not in the skia but it's in the ranimated uh let's let's look for clamp in poate extrapolation clamp yeah let's do extrapolation clamp in order to say that hey don't go more than minus 0.5 and more above that one let's import extrapolation from ranimated and now it yeah even if the speed is going to be way higher it's not going to go above because I can show you the example if we don't have this one and if for example instead of 500 we're going to have 50 it's going to be clear what I mean by that you see see uh that means that the rotation will go beyond like the the values that we have here but if we set clamp we're basically saying like don't go above these values so as you can see here it moves up and down but not more than that value and I would move back to 500 because it's a better value nice perfect let's go ahead and do get OD bird rotation is it getting already too much hopefully not use Dan shiftman stuff from the coding train and Port it to react native that's exactly what I was thinking like I remember a couple of years ago I was watching coding train and I was having so much fun just looking at him building this let's say like we are useless um animations or simulations but they're so fun to build and you learn so much from them like basic programming or physics or mathematics and I was thinking like maybe I should do something like that in Rec native as well and definitely coding train has a lot of this one loved he love his channel I'm not sure if he's still doing it said is saying heyim you and Simon are one of my favorite native developers I've learned a lot from you especially during November thanks a lot thank you very much appreciate that if you enjoy what we're doing make sure to subscribe to the channel guys because from the analytics I see that only 1% of people who are watching the videos are subscribed so make sure to subscribe and comment down below 1% gang we're we're going to know what what that means all right so let's go back to our game uh and what I want to do next probably is going to be a little bit more tricky uh and we will do okay let's try should I do first keeping track of a square or maybe yeah let's try to start by keeping track of a score keeping track of of the score when should we increase the score we should increase the score if you think like logically about it is when the bird passes through the pipes but because the bird is not moving it's actually our pipes moving on the screen so in fact we should increase the score when the pipes move move from the left side of a screen to the right side of a screen like they pass the halfway the halfway there where okay calm down V uh so let's go ahead and do that that means that we are going to have to increase the score based on this x value the x is what moves our pipes that means that we're going to check when X moves past half of a screen to do that uh my mind says that I don't have it prepared but where is the use animation uh use reaction how is it called animation reaction use animated reaction allows you to respond to changes in a shared value it's especially useful when comparing values previously stored in the shared value with the current one exactly we want to compare to check if previous value was on the right side of the screen but now it's on the left side of the screen that means that it's time to increase the score so let's add a use animated reaction I will H let me change a couple of things in my code for example the use effect I would move it right at the top I don't know where maybe yeah before this one gesture frame call back yeah I think that's okay the dered value for transform and origin maybe I will move them at the bottom um because they are calculated values I'll keep like let's say state or values that change at the top then our effects uh then our functions or gestures and only when we der right value that we kind of calculate so now uh we have the x value here we are moving it inside the use effect so it's logical to have the the animated reaction after the use effect here so let's copy it from the documentation let's paste it here let's import it from reanimated and the first one is the value that we want to react to so that's going to be our x dot value I can simplify this a bit by removing this just just like this as simple as that then we have current value and previous value so if current value more than previous value do something const console log the map moved to and here it's I don't know current value so we should see this being called very often but what we are interested in restart is when it passes this half of the screen Mark the half of the screen uh yeah let's check it let's check it so if current value is different than than previous value uh con uh middle equal with the WID of the screen divided by two now I will do if also the current value is on the left side of the middle of a screen so if it's less than the middle and if the previous value was on the right side it's more than the middle uh then we're going to do score plus plus we're going to increase the score but previous value can be null if previous value if previous value but wait wait a second wait a second why have the same uh operation in both cases I want to say if current value value is less than middle but previous was more than middle so it should be more than middle and here I will do if previous value or zero or I can default it to zero I can do here and previous value maybe if it exist at all okay and I would also have to do one of them should have a equal sign because if the current value is right in the center it might not work so I will have to do less than or equal on either of them it doesn't matter just to make sure that at least once it takes into account this so let's reload and see how it's happening Plus+ plus plus and we see that is happening right at that middle hopefully uh maybe we are also going to have to deal with decreasing it a bit or adjusting it based on the weave of the of the pipe but we're going to figure this out later when maybe we will we will um we will finish implementing everything and we will polish it but the think is that we can detect when this happens using a an animated reaction we are increasing the score but not actually increasing it should we keep the squore as a shared value or as a state um I don't know let's see in ask K can we render text yes we can render text the text component can be used to draw a simple text paragraph I need probably text simple text glips text PA oh nice text blob so let's uh I don't know let's try to define the score State set score um and we're going to see we're going to see maybe it should be a shared value use State initially is going to be zero when we do V Square ++ let's call set square and and we're going to take the current score and we are going to increase it by one maybe it's not going to want to do it because the set score is is um is a state value and the state value lives on the JavaScript Fred a state value leaves on the JavaScript Fred but the use animated reaction runs on the UI Fred so it has access to Shared values which are also in the UI Fred but it doesn't have access to the setter that is on the JavaScript FR uh for that I'm not sure how like why we would need a state or a shared value so if I would still like to continue with a state probably I would have to use the run on GS function imported from reanimated here we send um function that we want to run and in the second set of parentheses we send the parameters so this will run the set Square function on the JavaScript thread by passing there these parameters so maybe it's going to work I'm not sure let's give it a try but anyway I don't know why I want it to be a state anyway it worked so let's try to to render it on the screen I will run as a re native ke at text so let's do text here let's see text here it just need X and Y so let's go probably after we render the background maybe even add the bottom because it needs to be on top of everything else uh after our bird group but also in the canvas let's render the square text come on text uh string or text score probably two string and we need the x of I don't know 100 and Y 100 just to see it on the screen and then we're going to think about them and closing as well okay it's object doob Square to string is object doob come on what hello hello and if I do hello and then Square it's object. object to string object. object what to wait a second uh I need to to see it right right at the beginning uh how performance yeah at the beginning is zero then it's object do object that means that the way I set it back doesn't work correctly set Square uh what if I do square + one here will it work square one two yes it works okay perfect so what do we have score I don't even need this one to string is going to be enough uh for the Y it's okay X is going to be with divided by two to be somehow in the middle what else does it have font font size what hello world why it uses font size I don't understand the Y is the Y position why how to increase the font size font style how do you give font style and where do you give it match font font style oh match font so I can play a bit with 40 I don't know is not assign to parameter font weight or in string is not to font weight 700 what let's try let's give it just font okay okay okay it worked so yep color can I change color here I don't know but I'm okay with that almost it's very hard to center it like this okay it's it's something so a f if I do here a group do a f it's going to use that as a color I don't know okay we have something at least we have a score scoring system the I realize yeah the our score increases too soon it increases when the pipes passes the middle of the screen however we moved the position of our Burns a bit to the to the left of the screen so we should increase it when the pipes passes the position of a bird so if I check the bird it has x equal to width ided 4 let's use this as the bird position dox let's define it somewhere here as the const bird position as an object X and it will also have y for now it's only X should it be bird PA yes bird PA X and we're going to use this bird position in the in the animated direction to check not the Middle Point but uh yeah let's do middle here bose. x that why it should be declar a bit more to the top bird y it's getting a bit messy I'm getting a bit uh tired we have a bird pose and we have bird y shared value H but it's okay so let's just see if the timing is right yeah now the timing is right like when the bird passes through the pipes that's when we increase the the square that's good and if we later decide to move the the bird to I don't know the position 50 like very close to the to the left or even like 10 it's still going to work and the matching like it's going to be synchronized okay that's good let's go back to weave over four okay nice looking good okay so that's our gate status sore okay we have a squore the next one is going to be Collision detection to stop the game when we t touch something C subscribe and turn on the Bell thank you very much which vest code theme are you using I don't know should be the material theme I have a a video about that it's the material darker material feed I think it's this one oh this one material theme and from it it's specifically the the darker one I think all right so Collision detection there are a lot of collision detections that we have to do uh but I think the Collision detection is also going to be an animated reaction but this time on the bird y so every time the bird y position is going to change because the X never changes the X Remains the Same the bird y position goes up and down and every time it happens we should check if it collides with something so let's define here let's do here the scoring system and we're going to Define below the Collision detection which is also going to be an animated reaction uh that will be triggered when the bird Y bird y dot value is going to change so we are going to get back the current value and the previous value and let's let's basically do the following basically if current position if current value or yeah if current value is more than the screen uh height that means that the bird went to fell down right let's do a simple console log game over the simplest Collision detection is going to be with a ground because that is detecting a collision between an object and a line so what we do here let me open up this one so after it passes it's game over so we simply compare the Y position of our object with the with a line with the height of the screen in fact we don't need the height of a screen because there is also this ground so let me do the next thing let me Define a shared value const game over equal use shared value and it's going to be false now let's see simply when we do that let's simply do game over dot value equal true now I want to stop some of the movements when the game is over uh for example I want to no longer do the where is it frame callback when we are moving the bird around I want to stop that from happening so let's stop the execution of this function when the game is over so if game over is true then I don't want to do anything now we see the game over only once the thing is that it happens when the bird is already below the screen I think we're going to have to do in this check where is it in Collision detection when we check the current value if it's more than height we should subtract here the height of our base in the height of our base if we look in the base height 150 so let's do that here oh it's getting already interesting to navigate so height minus 150 now I expect the bird to stop when it touches this base does that make sense I think so maybe we can do 100 boom and uh it crashed okay that's good the next step is I want to also stop the map from moving right to do that our map is moved by this use effect at the beginning of uh our application mounting and we are starting it using this with repeat with sequence and so on if only there would be a way to stop this animation on the x value well a good thing is there is so in the Collision detection when the game is over and actually I'm going to add another not to have to call this okay let me actually call it first I can call cancel animation from react native reanimated on the x value if I do that hopefully it's going to work should I do cancel animation X yes it works so we are cancelling the animation a better way would be to watch for the game over value change using an animation animated reaction and only van cancel this animation because we don't want to do it like always like this I think so yeah so I'm going to add here let me copy paste this one but now is going to look for game over do value and if current value if current value or current currently it's game over but previously it wasn't game over previous value it wasn't game over that means that we can cancel the animation on X will that work boom stop if current value and and previous value not were stop yes perfect perfect perfect okay okay okay uh so we have some kind of game over State here um I was trying to shock to to to show like a popup to the user and I was trying to use a simple alert. alert but of course we're not going to be able to do it here because we are on the we are on the UI Fred so I was thinking okay if we're on the UI Fred we're going to use a run on GS we're going to use the alert. alert here and we're going to pass here game over but for me didn't work so I'm not sure why uh when we crash it's still crashes the application this alert alert so what should I do [Music] better anyway I'm not going to alert anything uh but whenever we press on the screen once again I'm going to restart the game what do you think let's try it like this so I'm going to do in the gestures when we when we tab I'm going to check if the game over value is is true restart otherwise jump we already know how to jump how to restart so jumping still works and when the game is over I want here to restart how by let's doing here cons to restart restart game equal function let's call it here and what should happen when we restart the game well first of all we need to reserve the position of a bird so bird y. value is going to be to its initial position what was the initial position that we set bird y hide three so let's see if at least the bird restart game think it should be a workl no or yes yes it should be a workl so simply doing use worklet will that fix boom where just worklet because this function we need to Define it also on the UI frad so that the gesture can call it okay now it works so if I simply do worklet here we can call it from our gesture uh we reset the bird y value we also should resert its velocity so bird because if it was falling before I want the velocity how is it called come on bird y velocity I'm getting lost already dot value is going to be equal to zero and what else what else that game over is going to be value is going to be equal to false we're going to restart the game the score is going to be equal reset to zero what else would happen but here I'm not sure if it's going to work yes because set score should run on GS run on GS set score and value zero and the next step is we should restart the animation of uh moving the pipes the animation moving the pipes was started here in this use effect let's take it out into a separate function called const move the map and in the use effect we're going to call move a map and the same thing we will do when we restart the game we will call move the map doesn't want to work maybe also run on GS move a map like this let's try boom we restart we start over moving the map it comes back to this position I'm not sure why but I will do the following I'm going to change the value of x to the initial value that it had X is going to be with so now it crashed if I restart we start over from x0 two we crash game over we start again you have cancel animation X twice cancel animation yes that's true that means that if I'm canceling animation based on an animated reaction over the game over I don't have to do it here as well so that was the benefit of putting into a separate one because I'm going to change the game over in multiple places is not only here this is only uh floor floor or ground ground Collision detection I'll probably have to also do the same for the ceiling like if I go very high up uh I would also do game over but I can do it also here if current value is more than height or if current value is less than zero that means that we went too high so if I'm going to go boom game over and restart from the beginning boom crash it just restarts it very fast so okay okay now the interesting part we need the um we need the Collision detection between the bird and the pipes how do we do that well uh we know the position of a bird we know the position of the pipes we just have to put them together somehow and do the detection um I can do I can start very simple I can say if the bird if the bird position matches the position of the pipes then let's consider it uh as game over so that means if this is current bird position if current value is equal to X do value and X is our Map X is our pipes if it equal where let's say yeah let's not it shouldn't be equal it should be current value is more or equal than the x value let's do game over so that would mean that current value if current value is less or equal than x value H what's happening did you stop working current value if current value is less no if should be if it's more than x value and why are you stop right now current value and x. value oh because I'm checking the the bird y value I should work with uh bird position dox so bir position. X good now as soon as as soon as I go here and it actually works B in the middle as soon as that happens game over uh x value X so what I need to add here oh boy Let's uh let's um search for some uh formulas for um for Collision detection because what we actually like I as I remember from from game development we should basically consider them as either um a collision between a circle which is our bird and different uh rectangles like different rectangles like this so knowing the the position of rectangles and knowing the position of a circle and its size we can calculate which of these it is touching it is basically colliding with so I think that's what we should do so let's go ahead and do here Collision detection uh sphere or Circle and rectangle okay so I I'm also trying to think like which one is going to be easier Circle and uh um rectangle or rectangle and rectangle what was the previous one Collision detection rectangle rectangle Point Collision detection Point rectangle maybe I should just consider a the bird as a point I think it's going to be easier because I don't have to take into consideration the radius and so on what's even easier yeah let's try with uh with point and rectangle so Ching for for collision with circular object is fairly easy since is the same distance from the center to their Edge in every direction rectangles require a bit more complex algorith let's say we have a square uh rectangle X rectangle y rectangle width and height to see if points but if a point is inside the square we have to test is the X position of a point to the right of the left Edge then we have to check if is the X position of a point to the left or the right Edge if it's below and at the Top If all of these are true then the point is inside let's look at testing the left Edge first since the default mode for react rect command draws from the upper left corner okay so let's look at testing the left Edge first left Edge first this is point this is rectangle okay let's do the following oh complicated complicated uh so we have bird X and bird y I want to draw instead of a image I want to draw a simple circle circle it's not on the background but it's going to be on top of a bird Circle we kind of the same things but a circle has radius skia Circle Center center radius CX see y why it's not X and Y I don't know and and radius of let's say five pixels okay we see the dot there burn why burn let's try to reenter the center of the bird over actually the center of a bird I'm going to do that using a derived value so let's do const Bird Center is going to be a use derived value and this use derived value is going to return us the X which is going to be x. value and Y is going to be not X Dov value bird position dox and bird and bird one y dot value I'll start with this uh which is going to be the same exact values but I'm going tojust them in a second now for this dot that we see on the screen let's go ahead and say that the dot we are tracking is going to be Bird Center dot value dot Y and then Bird Center dot do value do X and you are not moving oh [Music] boy because they should be Bird yeah they should be two different derived values so Bird Center X and then Bird Center y and Bird Center X is going to be this one and Y is going to be this one let's work with a center just to have Clarity Bird Center Y and Bird Center X now as it moves it follows the bird but I will recenter it to the middle of a bird by adding half of our bird width and height so 6448 64 for the X we are going to add 32 and here we're going to add 24 okay now the dot is exactly in the center of the bird Circle color can I do that color red will it work yes or maybe white purple I don't know or I'm going to Simply remove a bird alog together and have it as a Red Dot now we are working with a red dot which I can increase a bit in size and then we are going to yeah we have a red dot the rectangles are going to be the two of our pipes right let's again work with with them I want to draw two boxes on the screen just for us to know what we're working with to have a visual representation uh so in the paths I'm going to have what polygons for the rect X Y width and height so here Sim we're going to have a rect rectangle that is going to be our first um first box correct where is our pipes pipe offset x with and height oh boy um why is it 1003 maybe 104 supposed to be pipe uh so let's go ahead and add this to to a constant pipe width and height const pipe with is equal to how how much 104 const pipe height is equal to 320 something like that oh 640 pipe with and this one is pipe height which should be a bit different 640 let's go to the top 640 uh I think I'm going to not draw the rectangles there I'm going to use like what we see here because it's the same X Y with and height now let's go ahead and check a little bit of the Collision detection algorithm here so the first thing as we say like we have to do four checks for every single uh pipe so let's go ahead and do here in our Collision detection use animated uh position um top pipe let's work with a top pipe or even let's start with bottom pipe we're not going to work with bird position but Center bird uh Center X or Y uh X dot value uh let's go ahead and check the first one if all of this are to let's look at testing the left Edge first since the default mode uh okay draws from upper left corner the left Edge is at rectangle x to the right of a rectangle so if point x and our point x is bird I'm going to do it like this if bird center. value is more that the rectangle X and we're talking about the bottom pipe let's check what is the RX of our bottom pipe I'm going to go here I'm going to check for the where we render the pipes the x of the bottom pipe well the x is the X so it's going to be the same our X is going to be simply X do value to the right of the left Edge so the bird is to the right of the left Edge okay perfect uh console log to the right so when we go here we get to the right which is basically what I had before Exposition which is the left Edge Plus the WID to the left or the right Edge so right over left left over right okay this is going to get interesting so then we have this is the first check then we need this one PX is point x it's our bird value do X RX is going to be the x of the of the of our pipe and our V is going to be the wi of our pipe so that's our pipe wi so now we know that the point is exactly in between the the two things it's but it should be end here yes end reload what I'm going to do probably is maybe I can now we need to check if it's below the top and above the bottom this are last two checks below the top py is the point it's our Bird Center y do value r y is the r y is our bottom pipe y value so it's this one we need to take it exactly how it was there r y and here again py is our Bird Center Y is the point we calculated for should have end here r y is going to again we're going to take it from the Y of the bottom Pipe Plus the height of the pipe so that's going to be pipe height so now we should properly have game over detection with bottom pipe let's check if that works so with the top one we don't yet have uh detections but with bottom one we should so if I'm going to go and touch it doesn't work where is the pipe offset pipe offset maybe I should do it at the top somewhere oh now it worked if I'm going to go touch it from the top it also works if I'm going to touch from the from the side it also works so it works oh my God so happy oh boy amazing perfect so uh the same way as we have here for the bottom pipe we should do with the top pipe we can copy paste it top pipe uh and the only thing that will change the burp Position will not change like this will stay will remain the same the x value is not going to change the pipe with pipe offset not going to change only thing that is going to change is the this value like where is the top the Y value from the top pipe the Y value from the top pipe is pipe offset minus 320 so here instead of this thing we're going to have pipe offset minus this and here we're going to have this now I think we should have proper detection for both of these pipes here it works works works works I think it works perfect so now I can remove the dot and add back the bird but just remember that we are yeah checking the Collision based on the center of a bird which is nice which works pretty okay oh my god it works yeah boy okay so it wasn't actually that complicated when we have a formula um most probably we can improve this thing by having a list of obstacles as x y and um X Y we and height and then looping through them and checking their value so I think that's what I'm going to try to do now let's go ahead and create a derived value with const obstacles which is going to be an array of obstacles that we need to check using this detection so let's do use derived value and it's going to return an array or let's do const response equal to this all obstacles now let's do add top bottom pipe then add top pipe let's go ahead and do all obstacles dot uh push and we're going to push an object with values that are very similar to this one rectangle X rectangle uh y rectangle W and rectangle height were even easier uh x y height and width these are the four values that four four values that we need to provide about one uh obstacle so for the bottom pipe I'm going to go into the if statement that we have here bottom pipe let me check so the x is going to be x value the Y one second yeah so the x is going to be x. value the height is going to be pipe height the wi is going to be pipe wi and that Y is going to be I'm going to go and take it from actually the Y way we render it so pipes the bottom one the Y is this one so in here in the obstacles I'm going to add it here and now I should do the same for the top pipe X is going to be x value Y is going to be different so let's go and take a different y from here this one for the top pipe I'm going to change the Y now we have uh now at the end we should return all obstacles we have top pipe and bottom pipe in the Collision detection what I should do is I should basically uh I'll Define a function const is Collide colliding with rect or let's say is point colliding with rect this is going to be a function that will do most of a things that we have here let's do it like this but it's going to be much more easy to work with because we are going to have here a a point and a rectangle then this one becomes the point dox so this one becomes point dox the same here point dox here Point doy and here Point doy on B hand we have r.x here re dox multiply by re. wi here we have rect dot Y and at the bottom rect Dot y plus rect dot height so it's very similar to the formula that we see here RX RV r y plus r height so if this is happening I'm going to Simply return true or I can simply return the whole thing like return this because we use it in an animated reaction this should run on the maybe it's going to work but we'll see if it fails we're going to make it a work Le so what I want to do right now is I can check for the bottom pipe I don't even need like to check separately for the bottom pipe and for the top pipe I only have to do const is ciding and I'm going to take all the obstacles dot value and if at least one of them one of this obstacle which is rectangle if at least one of them is point colliding where the point is going to be it needs an X with bird center. X and it it needs a y with Bird Center y do value and it needs a rectangle which is our rect if at least one of them is true then it's going to be is colliding so if is colliding game over equal true or game over. value equal true so maybe here like like I lost you a bit I realized but instead of basically doing this for two of them if in future we're going to have more pipes and more obstacles it's going to be hard to check for all of them instead we create an array of these obstacles at the top and then we'll Loop them and check if our point is colliding with at least one of them let's check right now if I'm going to open yeah I think it's uh it actually needs here uh to be a worklet work CL because we are calling it from the UI okay it doesn't actually work with the top one does it work with the bottom one no bird x. value rect let me check console log point point and W here point and W H vxy oh it shouldn't be with but W and here H HV vxy H vxy Works boom works so perfect now it works amazing amazing oh that was hard where is the console log I don't need it anymore let me do get add get commit uh Collision detection oh perfect so um another thing that I want to add for the game to be more interesting is for the pipes like for The Gap to be at different position right now it's always in the center of the screen uh but I can change that by simply changing the pipe offset so we see that we have here pipe offset and now if I'm going to change from from a normal value to a use shared value zero let's see what do we have I'm going to check where we are using this pipe offset and I'm going to use dot value and where else here pipe offset do value pipe offset do value uh it's not going to work it's not going to work pipe offset pipe offset don't value it's not going to change that's the problem because if after the first reset or let's say this is the squaring system with the X but I can add here also the way to change uh stuff around because if the current value is less than is less than zero and the previous value is more than zero I want [Music] to I want to change the offset with a random value so pipe offset equal to Value equal to MAF do random multiply by 10 or multiply by 100 and then minus 50 to be able to move up and down it's still here but ah you see like it changes not when it has to change h it only doesn't update properly because I am sending here to the to the Y of the top pipe it should be a a shared value so again another shared value const pipe let's do pipe top pipe y equal use derived value uh and the value is going to be top pipe y let's check it's going to be top pipe y. value and I'm going to take it from here put it in P dve value the same for the second one bottom pipe y it's going to be bottom pipe and the value I'm going to copy it from here of all these calculations so now it should work why it changes ever so slightly here if previous value and current value is less than zero and previous value is more than that for 400 and 200 what current value this is the X Change change offset I want to change offset only when they go to to the end of the screen the change offset works correctly value time anyway why does it change when okay okay okay I know I know I know I know I should check not based on zero here but based on minus 100 Maybe it's still not how I want it uh when we render pipes yes because I still use value I should use the the actual shared value without dot yeah now it should work perfect okay now it's getting more interesting okay boom okay now it's it's fun to play okay so we have uh uh change offet change offset for the position of the next Gap let's go ahead and do G add G commit minus M uh random Gap position I'm already very happy with where we got so far what do you think guys pretty cool right sometimes it goes sideways but most of the time it works pretty well anyway I think there is a lot of uh opportunity for improvement here um maybe we can cover some of it right now not a lot but at least some of it like with a bird position being uh being uh an object with only X I think where do we use it let's check in Bur position X bur position x x x maybe it's smarter to do bird position x equal to W over four because we have bird Y and maybe even bird X not bird position bird Y bird X now let's check where we use it and make sure to change it to bird X simply here bird X here bird X now it makes a little bit more sense reload hopefully it's still working come on oh I need here okay Bird Center let's do that this one here right after the positions Bird Center where do we use it let's check how many places we are using it uh is colliding Bird Center Bird Center we are no longer rendering this simulation so it's really only used in this um Collision Det protection right so I would say that let's get rid of it because we are using only Veer let's not calculate the derived value out of it but simply create Veer because we don't need it any more for rendering something on the screen so I'm going to copy them from here cut them from here I'm going to scroll down where we use them let me paste at the top of this function and think about creating an object R Center equal to X is going to have this value bird X and Y is going to have this value now I will remove these two things and I have a center which I'm going to replace here here instead of bird center x.v value is going to be Center dox and here uh Center dot y but as you can see our is point colliding with rect expects an object with X and Y so why not simply sending here Center just like this let's see if it still works it works so we got rid of two uh derived values next thing um B yeah we have bird Y bird X bird velocity the pipes pipe offset pipe offset is good top pipe what bottom pipe y move the map maybe this x is is not very uh is not very clear what it is so let's do pipe dox pipe X and let's check here where we have this x so whenever we access X let's do pipe x. value here pipe x.v value be careful with this uh refactoring because sometimes we can break things but if you are careful of replacing all of the instances here cancel animation on the pipe x pipe x pipe X the next one is also pipe X and that's it it now it should work boom we restart it restarts okay nice what else what else obstacles like these obstacles it makes sense to have this push but I would simply have an array here with values right away because it's going to be much easier to to see uh but it can be a bit confusing so you can leave it like this but what I'm going to do is I'm going to get rid of the array itself I'm going to get rid of these push things I'm going to leave object right away I'm going to get rid of this push as well with this I'm going to get rid of return obstacle and I'm going to turn this one into an actual like return array and at the end I'm going to close this I need to put comma here so now it's simply an array with two objects I can as well remove a return statement and this bracket and it's even easier so bottom pipe top pipe like this makes sense let's see if it still works top pipe Works nice bottom pipe Works what else I don't like this one is nice because it's a reusable function that we can use based on any point with any rectangle we can check if it's colliding or not yeah now it's a little bit more clean let me go ahead and do get add get commit minus M refactor you can keep track of a high score system uh what if you for example want to increase the speed of um if you want to increase the speed of of how fast the pipes are moving well first of all what [Music] what what influences the speed of how fast the pipes are moving it's this duration because if I would do here 1,000 you're going to see that these pipes are moving very fast I don't even manage to do it like one five so what you can do is you we can take this duration put it into a or let's do a shared value for pipe speed right const pipes speed equal use shared value one if we're going to increase the speed we want to increase the value of how fast the pipes are moving so that means that the duration divided by pipe pipe speed dot value so if we increase the pipe speed the duration is going to decrease so the speed is going to increase basically but now yeah uh at this moment if it's one is going to go with this speed if we increase it to for example two that's going to be double the speed as we can see perfect now the last thing is to when do we increase the pipe speed well first of all I know for sure that when we do restart game when we restart the game uh uh we're going to do pipe or speed how is it called pipe speed equal dot value equal to one we're going to reset it to one but when in our soring system I think or you know what we can do with it pipe speed I can take the the score which is a state variable I don't know why I made it a state variable but pipe speed can instead of shared value it can be a derived value a derived value that will be calculated using an interpolation we're going to interpolate the sore so the higher the scare the higher the speed when the sare is zero I don't know sare uh 10 when the square is zero the speed I want it to be one when the score is 10 or maybe 20 I want the speed to be two maybe when the score is 10 let's just see how it works and in this case if it's a DED value I will not have to reset it in restart game it's going to depend on the score so now as we move as the sare increases the pipes should move faster I think I hope let me I I don't know if that's happening so I'm going to increase the speed not to two but to five so in this situation I'm going to know it's not going to change and I know why because we set this animation over pipes yeah we said the animation of the pipes once moveing map uh maybe I should not have a we repeat but instead call move the map again when we end it what if here we're going to do cancel animation on pipe x pipe X and then call again move map will it work I don't know let's try probably it's because of move map which is not a workl because without it it's not going to crash so let's try to do run on GS move map come on move map move move so the sequence uh when calling move MEC I think it should start by going there and it shouldn't it doesn't need the repeat because we're going to call it over and over again I don't know if it's going to work but let's try back into the Game Dev yes okay now it works and I can definitely see that the speed is increasing okay so I will um clamp it probably like a 20 it's going to be two to increase the speed but relatively okay how are you doing Andre how is your work at col stack okay now I can play I have uh what to do today but actually today uh F uh Netflix released the new season of F1 which I can't wait to go and see so I think that we are going to have to end the stream but it's so satisfying I was thinking to add also like sound effects but I didn't so this would be your homework to add sound effects using Expo AV now I can play oh you you have two accounts you're answering from the same name different avatars working on Native Dev how are you I'm good as well uh doing content working this week we started um the incubator program during which we're going to help Founders launch their startups that's also something exciting but yeah uh anyway guys I think that is it for today we have managed to do a lot of things let me do a git ad git commit increase um the speed I'm going to make sure to publish this on GitHub and Link uh the repository down below so that you can play around and continue working on it uh by adding different features maybe adding a nicer end screen uh maybe adding keeping track of a high score that should also not be very complic ated you would simply uh store it in on the local storage using our sync storage and compare it every time you finish the game uh I'd also add sound effects that would improve this application by a lot and I think that's it like nothing more maybe you can uh play around with the Sprite of numbers we have here 0 six and like all the numbers is sprit so if you are interested you can try to render them but that's probably going to be a lot of if statements uh but anyway uh thank you very much for joining I hope you enjoy this one um let's see maybe in future we're going to do more of this kind of nontraditional uh Rec native applications maybe some games some simulations some creative programming I would love to to prepare something for you so if you're interested make sure to uh let me know what projects you'd like me to build in future and um I'm going to try to do that anyway guys I'm going to go uh check out the F1 if you're also into F1 today is uh is the premiere of Netflix and next week we have a first races so very excited about that anyway subscribe to the channel turn on the notification Bell we're going live every single week
Info
Channel: notJustā€¤dev
Views: 6,870
Rating: undefined out of 5
Keywords: vadim savin, not just development, notjust.dev, react native live coding, live coding, react tutorial, react native tutorial, react native for beginners, React Native, step-by-step tutorial, game development, Flappy Bird, Reanimated animation, physics in React Native, programming games, React Native Skia game, React Native Reanimated game, Reanimated tutorial, flappy bird tutorial in react native, react native game engine, react native skia, react native animations
Id: 9F4aICEisVI
Channel Id: undefined
Length: 200min 37sec (12037 seconds)
Published: Sat Feb 24 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.