Build Your First Flutter Game with Flame | Apps From Scratch

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Love your videos.

👍︎︎ 1 👤︎︎ u/Mishuri 📅︎︎ Nov 13 2019 🗫︎ replies
Captions
hey everyone welcome back to my channel where you learned how to create amazing apps with flutter and Dart today I'm going to teach you how to build your first mobile game with flutter and a minimalistic game engine package called flame before I get started I want to let you all know that you can get a discount on algo expert by going to Hal go experto slash Marcus algo expert is a coding interview preparation platform that has a curated list of interview questions each with a comprehensive video explanation I highly recommend algo expert as I've been using it myself to prepare for my technical interviews and it's been very helpful if you're interested make sure to click the link in the description to get a discount with promo code Marcus and with that let's get started as always let's start in our pub spec Tom will file where we're going to import the flame and shared preferences packages flame is the minimalistic game engine that we're going to be using and shared preferences is going to allow us to store the users high score locally on their device let's go to our main dart file and we're going to start by clearing out everything in here so we can delete all that and we're gonna make the function void main in this function we're going to need to create a util which is from flame so let's make util and import the flame package will call it flame util equal to util and instantiate that next we're going to need to do a wait flame util dot fullscreen and because we're using a wait and our main function we need to make it a sink fullscreen ignores the status bar at the top of our app next we need to create flame util and we have to set the orientation to device orientation dot portrait up and that's going to keep our device orientation blocked in portrait mode and we need to import services start now if we hit save we get an error because we need to implement the run app method so let's type in run app and inside here we're going to need to pass in our game controller dot widget so above this let's create game controller game controller and set that equal to game controller now game controller is going to be a new file so inside our Lib directory let's make a new file called game underscore controller dot dart our a game controller dot dart will extend game and game is from the flame package and the game controller needs a constructor so let's make that it also needs three more methods the first one is going to be void render canvas see the next one will be void update and that'll take in a double T and the last one will be void resize sighs sighs and then make sure to import dart UI it's safe and going back to main let's import our a game controller it save and we can remove the test directory here because we're not testing any widgets so I delete on that let's it save now and not restart the app and we can see that we have a black screen our game controller is the brain of our game it contains all the instance variables and logic behind our game which we can display on our screen using the render method we can also update our game using the update method which takes in a time and we use the resize method to set the initial size of our screen let's create two instance variables to track our screen size the first instance variable will be size screen size and the second one will be double tile size the screen size will be the dimensions of our screen and the tile size will be a smaller portion of our screen the reason we need a tile size in our game is because when enemies move on our screen we want them to be able to move at the same speed no matter what screen size the user is playing on let's set up our resize method we will set our screen size equal size and then our tile size will be screen size dot width divided by 10 so the size of a tile in our game is a tenth of the width on any screen we need to call our resize method inside our constructor so let's make another method called initialize and we'll put it right under our constructor boid initialize and it'll be an async function and inside here we just call resize oh wait flame dot util dot initial dimensions and that's going to get the initial dimensions of any device run and we just need to import the flame library and spell initialize correctly now before we start coding any features of our game I'll explain how the game works the idea is that you're the player in the center of the screen and you have enemies spawning all around you in order to kill the enemies you have to tap on them three times and if they touch you they're going to deal damage to you so we'll have a health bar at the bottom of the screen which will decrease as enemies do damage to you and the more enemies you kill the higher your score is the goal of the game is to just survive as long as you can and kill as many enemies as possible let's create a background for our game inside the render method we're going to create a right background and set that equal to rect dot from L T WH which is left top with height and the rect will be from zero zero and the width will be screen size dot width and the height will be screen size dot height now we need to set a color for the background and the way to do that is by creating a pink we'll call it background paint equals paint color and set the color equal to zero x FF fa-fa-fa and all we have to do to draw the rectangle is do C draw rect background background paint and it safe and now we change the color of our background we set the left and top of our rectangle to 0 0 because our canvas is drawn from 0 0 up here and then the bottom right is screen size not width and screen size dot height now let's work on making a player spawn in the center of our screen so let's go to our live folder we're going to create a folder called components inside components we want to have player Dart flare that dart will be class player and we need to create the instance variables that the player will have the first one will be final game controller game controller make sure you import the game controller we're going to have a max health we're going to have current health a rectangle for the players hitbox and a boolean called is dead which will set the false our player needs to have a constructor and our constructor will taken this dot game controller and this will assign the game controller we pass in to the final game controller instance variable we have in the player now the first thing we want to set is the max health and we'll set that to 300 and we'll set the current health equal to 302 and since we're setting our max health and current health to the same variable we can actually put this on one line so we can say max health is equal to current health equal to 300 and that's up to both variables to 300 next we want to define the size of our player so we'll make a final variable called size and set that equal to game controller tile size and if we remember we set tile size to a tenth of the width no matter what the screen sizes and will make the player 1.5 times the size of a standard tile now we want to set the player rect and we need to import dart UI so player rect is equal to rect dot from left top with height and the left will set it to game controller dot screen size dot width divided by 2 since we want the player to be in the center of the screen so by doing what divided by 2 we're now in the center and now we need to vertically align so a game controller dot screen size dot height divided by 2 and then for the width and height here we'll just set that to size now let's it save and we need to write two more methods to have our player render on the screen the first one is render so avoid render and I'll take in canvas see and the second one is void update double T will create a paint variable we'll call it color paint and then we'll set the color equal to color 0xff and then to make it blue we'll just make it zero zero zero zero FF and then we just have to draw the rect on the canvas so C draw rect will draw the player rect and assign the color will leave the update method blank for now and just hit save and go to our game controller inside our game controller we need to make another variable it'll be a player and we'll call it player and make sure to import the player dart component now inside initialize we need to set the player equal to a player and it'll take in this this represents the game controller and we need to pass that in to our player because we ask for the game controller and that's that's the player's game controller here now it's at save and then to render the player we need to go to our render method and all I have to do is type in player dot render and pass in the canvas let's hit save and hot restart the app and now we see that our player render on the screen but we can clearly see that the player is not centered even though in our player that dart we said game controller dot screen size not width / 2 and then also the height divided by 2 which we thought would be the center what would happen is that we set the players top left to be the center of the screen so this point right here is actually the Sun of the screen and the way we can Center the player center is by going to our left top here so the left always do is subtract size divided by 2 now if we hit save I'll restart the app we see that the player moved over to the center of the screen but we need to fix the height still and that's the same thing we have to do so size divided by 2 here it's Save & hot restart the app so the players range Stan she ate it and now the players in the dead center of the screen so whenever you're trying to render a component on your screen and you want to be centered or at a certain point make sure to subtract the size of your component divide it by 2 so then the values here represent the middle of your component another thing to note is that the order you render your components in matters because right now our render method renders the background first and then after that we render the player so our player is on top of the background if we were to take this player dot render and put it behind the background and now it save we see that the player disappeared and if this happened you make sure that you put the player after if we comment out the background draw rect it save we see that the players here so what happened was that the player rendered first and then we rendered the background on top so make sure that when you are creating components and rendering them that you order them correctly next let's deal with taps on our screen because we want to be able to tap enemies let's scroll down and underneath our resize method let's make a new function called void on tap down and that will take tap down details D and for now let's just print out D global position it's save and when we click on the screen we can see that our debug console prints out the position we're clicking and for safety we want to bind this on top down method to our game so let's go to our main dart file and underneath run app we're going to make a tap gesture recognizer tapper equals tap gesture recognizer will set tapper dot on tap down equal to game controller dot on top down which is the method we just wrote and after that we just want to write flame util dot add gesture recognizer tapper and that properly binds the tap gesture recognizer we just wrote to our game it's saved and if we click here we see that our taps are still working correctly now we're ready to create enemies in our game let's go to our components directory and make a new file called enemy our class enemy and just like the player we're also going to have game controller so it make sure you import the file called game controller we're also going to have health we're going to have a variable called damage a speed which will be a double a rect for the hitbox of the enemy and just like the player we're going to have a boolean called is dead and set that equal to false now our enemy is going to have a constructor which will have this dot game controller and then it'll take in two other variables which will be x and y and those will be doubles x and y will be the coordinates that we want to spawn the enemy at let's assign the health her enemy so we'll make that equal to three and whenever we tap an enemy we just want to decrement the health by one and that's how we're gonna kill them we'll start damage equal to one so they do one damage the speed of the enemy will be equal to game controller tile size times two and then we want to assign a rectangle to the enemy rect so let's go up to the rect right here hit command period and import dart UI the enemy rect will be wrecked dot from left top with height it'll spawn at X to the left the top will be Y and then the width will set that to game controller tile size x one point two so enemies are just a little bit bigger than a tile in the game it will also set the height to tile size x one point two it's safe and then like our player we also need the two methods so void update TT and void render which will take in canvas see inside the render method let's assign three different colors to the enemy so what we're going to do is create color color and then we're gonna make a switch statement here so we can do switch and then take in health and inside the switch statement we're going to have three different cases the first case will be case one and that's if the enemy is at only one HP so we'll set the color to color 0x FF FF 7 f 7f will break case - that'll be color equals color 0x FF FF 4 C 4 C break and then case 3 color 0x ffff 4 5 0 0 break it save and then as the default case just in case we'll set the color equal to color 0x FF and make it completely red and break it save so now what this is doing it's going to check the health of our enemy and if it's 3 2 or 1 then we will set the color to these colors and these are all just different shades of red beneath this will make paint and we'll call it enemy color equals paint color and we'll set the color equal to color and then all I do is draw this on the canvas so see that draw rect which will take in the enemy rect and the paint will just be enemy color hit save to test this out let's try spawning an enemy on the screen now so back in our game controller let's make enemy enemy and remember to import the enemy component inside initialize will call enemy equals enemy this and then we also need to write the coordinates for it so we can just say 200 200 to spawn the enemy there and then we want to render the enemy after the player so we'll say enemy rendered see it save and let's hot restart the app and we see that the enemy appears now if we click on the enemy we see that we're clicking the position where the enemy is but we're not doing any damage so now let's add the functionality to kill enemies inside our on top-down function for now we'll just decrement the health of our enemy no matter where we click on the screen just so we can see the enemy change colors sold your enemy dot health - - and just hit save for now and if we click anywhere on the screen we see the enemy change to a different shade of red click again and changed again and now if we click it changes back to red but that means the enemy's health is zero so at that point we want to actually remove the enemy from the game let's go back to the enemy art file and let's write the code to decrement the enemy's health so or make void on top down and all we have to do is check if the enemy is not dead exclamation point is dead then we want to decrement the health by one then we say if the health is less than or equal to zero then we're going to set is dead equal to true and then here's where we're gonna deal with scoring in the future so for now I'll just write score [Music] the update method is what's going to allow us to move our enemy towards our player because we want the enemy to spawn and then instantly start moving towards the center of the screen which is where a player's I so we can check if our enemy is not dead then we're going to create something called step distance and step distance would just be speed times the time and if you remember before we set the speed of our enemy to our tile size times two next let's make a variable that's an offset and call it two player and this is going to be the coordinate position of our player I will make it equal to game controller dot player dot player right dot Center and then to check if our enemy is walking towards the player all have to do is do step distance is less than or equal to two player dot distance and that's the magnitude of the offset and then we need to create another offset called step to player and we'll call it offset dot from direction to player dot direction and step distance so that's how the enemy knows which direction to move towards and all we have to do is call enemy rect and set that equal to enemy rect dot shift step to player and the shift method moves our enemy towards the location we specified now if we hit save hot restart the app we see that our enemy spawned but it's not moving towards the player and that's because we need to go back to our game controller and inside our update method we need to call enemy update and pass in the time we see that the enemy starts moving away from the player it seems to be going somewhere else so we need to go back to the enemy dark and the problem with this function is that we didn't set our two player correctly we need to subtract the enemy rect dot Center and now if we hit save I'll resort the app we the enemy moves towards the player so if we don't subtract enemy wrecked out center we have the enemy going off somewhere in the distance but when we do subtract it the enemy goes right to the player and ends up sitting on top of him an easy way to put some distance between the enemy and the player is by just subtracting gamecontroller tile size times 1.25 from our player distance it's save I'll restart the app and we see that our enemy stops right next to the player and when we have more enemy spawning they're not all going to pile on top of him so they'll be sitting around the player and it makes it easier for the user to tap each enemy let's give the enemies the ability to attack the player so we're going to write a function called void attack and we're going to check if the player is dead by going to our game controller now player dot is dead so if the player is not dead then we want to decrease the players current health by our damage which in this case is just 1 and now if we go to our player we don't have a way to check the player actually dies but as we just made in our enemy method we can actually do the check inside our update so let's go to player the update will just contain if the player is not dead and the current health is less than or equal to zero then we'll set is that equal to true and then we want to reset the game which we will do in a second but for now let's just print out the player's health in here so we'll print current health it save hot restart the app and then we have to remember the insider game controller we also need to call player update T so that method runs we see that our health is 300 and it's not decreasing because inside the enemy door file need to check if the enemy is in range so in this F block we're saying if the enemy is not in range of the player and move towards the player if the enemy is in range then we attack the player now if we hit save we see that our players health is decreasing rapidly and once we hit zero it stops at zero now I think it'd be helpful if we had a health bar to our player and we can just have the health bar sit down here so let's create a new component called health bar dart and that will be class health bar and the instance variables will be final game controller game controller and make sure to import the game controller next we have a rectangle which will be health bar rect and the second rectangle will be remaining health rent so health bar rect will be a red bar and then the remaining health rect will be a green bar let's render it on top of the red bar as we take more damage the remaining health rect will decrease revealing the red health bar behind it so it's import dart UI here create health bar this docking controller and first we'll define a bar with and we'll set the bar with equal to game controller dot screen size dot width divided by 1.75 so that's a little bit bigger than half of the width of our screen next let's set our health bar rect and we'll set that equal to rect dot from LT WH the left will be game controller dot width divided by 2 so that horizontally centers our health bar and then we need to minus the bar width divided by 2 which is similar to why we - the enemy size and - the player size whenever we set the position and then for the top we set that to game controller dot screen size height times 0.8 we multiply the screen size height by 0.8 and that would put it around here because remember we're rendering zero zero up here and then the max screen size that height is down here and the max screen size not with is here so by multiplying by point eight it would put us right around here with the health bar well let's fix this typo here fighting screen size and then the width will just be bar width and then for the height we'll set that to game controller dot tile size times zero point five so our height of our health bar would be half the size of a tile now for the remaining health let's just copy this and change health bar to remaining health right now let's write our render method void render canvas C and the update will be right underneath that which will take in TT renderer we'll have paint health bar color and then we'll Stan shape paint with the color equals color zero x FF and we'll make this completely red so that's ff0000 d paint for the remaining health will be a solid green set the color equal to color 0 x FF 0 0 FF 0 0 and now we just need to draw the health bars in the canvas so C draw rect remember to draw the health bar first so health bar erect health bar a color and then we have see draw rect remaining health rect remaining bar color let's it save and then for the update method we want to update the remaining health rect so the size of the remaining health rect decreases proportionally to how much health the player has and then we can see an accurate depiction of how much health we have left so let's start by creating the bar with again so bar width equals game controller dot screen size dot with and once again that's divided by 1.75 then we need to create a percent health variable so percent health will just be game controller dot player dot current health divided by game controller dot player dot max health and that's going to return the decimal of our current health divided by our max health then we need to alter the remaining health rect equals rect dot from left top with height and we can actually just copy this right here so exactly what we wrote before and the only thing that's different is our bar width so we just do bar width times the percent health and it safe let's work on rendering our new health bar to the screen inside our game controller we create a health bar component health bar inside initialize you can make health bar equals health bar this and then for rendering we want the health bar to render on top of all of our components so even if enemies go over it they're actually going to be rendered underneath it so health bar dot render see and then update health bar update T it save etat restart then we see the enemy come towards us and it starts attacking us and we see our health bar decrease proportionally and then once we at zero we see zero here we're now ready to create the enemy spawner so let's first go to the top of our a game controller and instead of having only one enemy on the screen we want to have multiple enemies so we need to change enemy to a list of enemies and we'll change the variable to enemies inside initialise we can change enemy to enemies equals an empty list of enemy and now inside the render method we're going to change enemy to enemies dot for each enemy enemy so we can do enemy dot render and pass in the canvas so what this for each loop does is that it loops through our enemies list and then for each enemy it renders the enemy on the screen and then the same thing for our update method let's remove this under me here and then paste this and change enemy dot render to enemy FD and pass in T it save and then down in our on top down method we can actually modify this to check if we tap on an enemy and the way we do that is by doing enemies dot for each we get an enemy and we check if enemy the enemy wrecked sorry a new hit box that contains DEET global position so we're checking if the enemy wrecked contains the position we just tapped and if it does then we just call the enemy dot on top down method [Music] now let's at save and if we had restart the app we see that the enemy disappeared we can now write the function to actually spawn enemies on the screen so underneath our on top down let's make void spawn enemy and it's going to have double x and y and x and y are going to represent the coordinate position of the enemy that we want to spawn in so let's make a switch statement and that's gonna take in random integer and in order to use R and we need to create a variable at the very top called random R and and remember to import Dartmouth and that gives us the ability to generate a random number so in here we're gonna have four cases case ero case 1 case 2 in case 3 the idea is that the spawn enemy function will have four different places where the enemy can spawn we have the top the right side the bottom and the left for the top case we'll label the top we want to assign a random double to our x value so in this case our x value would be positive and we want to spawn anywhere along the screen size dot width so we can easily do that by setting X equal to R and dot next double and then just multiplying it by the screen size dot with for Y in this case we want it to be constant since the enemy is spawning at the top of the screen and want to be just a bit off the screen so enemies can spawn anywhere up here at any width so we just have to set our y equal to a negative tile size times 2.5 so if you guys remember we render at 0 0 in the top left so X would be anywhere along this range and then Y it would be 2 point 5 tiles in the negative direction so up here and now enemies would spawn up here and then move towards the player so they're coming from off the screen now for a case one that's going to be the right side and in this case we want the x-value to be constant so we're going to set it to screen size dot width plus tile size times two point five now this is screen size over here so it goes all the way over here to the right and then we add a tile size times two point five which brings the enemy to spawn just right outside the right side of the screen now why would just be R and X double x screen size dot height and that can be positive because the positive value for the height is all the way down here so it can spawn anywhere along this line and then case two would be the bottom X would be random next double time screen size dot with so same thing has our keys for the top but our Y would be screen size height plus tile size times two point five and the reason we add screen size dot height is the same reason why we add screen size not within the last one we need to go all the way down here and then we add the tile size times two point five so now we're just right outside the screen case three is the left side X would equal the negative tile size times two point five and Y would be the random nextdouble times the screen size dot height so the enemy can spawn anywhere along the height and the X is negative tile size times two point five because we need to be in the negatives to spawn just right outside the screen and remember to add break after each one of these cases right after our switch statement all we have to do is enemies dot add and pass in a new enemy with this and the coordinates XY it save and this function would now spawn an enemy at any location outside we can actually test this right now if inside initialize we just call spawn enemy and let's Hawtree sort the app and we get this error saying that next in was called a null so let's double check that we have the random R and here and what I forgot to do was initialize it and initialize so right after resize let's just add R and equals random now we hit save I'll restart the app once again enemy spawns off the screen and starts attacking us we can also test killing enemies by clicking them so we tap once we see the color changes tap again color changes again one more time and the enemy becomes fully red so let's just implement the feature that kills the enemies and removes them off the screen inside enemy dark we check if the enemy is not dead will you decrease their health and if their health is less than or equal to zero then we set the variable is dead to true now inside the game controller we're going to add another loop over the enemies and we're going to call it remove where we get an enemy back and we can just say enemy dot is dead now if we hit save we see the enemy disappeared and what this is doing is that it's looping over the enemies list getting an enemy if the enemy is dead then the enemy gets removed from the enemy list and that's why the enemy does not get rendered anymore let's create our enemy spawner now inside our Lib folder let's make a new file and we'll call it enemy underscore spawner dart class enemy spawner it'll take in final game controller make sure to import it game controller and we'll also have a bunch of integers to keep track of the spawn intervals so let's make final in max ball and interval set equal to 3000 final and min spawn interval set this equal to 700 final in interval change equals 3 final in Max enemies we'll set that equal to 7 I love enter for the current interval and then an integer for the next spawn and I'll explain all of these variables as we use them in our code but for a quick overview we have the Mac spawn interval which represents the maximum amount of time between each spawn and we set it to 3,000 milliseconds which is also 3 seconds for our min spawn interval we set it to 700 milliseconds which is 0.7 of a second this is the least amount of time between spawns interval change represents how fast we're going to be decreasing our interval by so as we spawn more enemies we will decrement how fast our spawn interval is so we can spawn enemies faster maximum enemies represents the amount of enemies we can have on the screen at one time current interval is the current interval that we're spawning at and next spawn is the time we're going to spawn the next enemy so let's make our enemy spawner constructor this dot game controller and then we'll call the function called initialize will have void initialize and in here we'll set the current interval equal to the max on interval which is 3 seconds and then we'll set the next spawn to the date/time dot now dot milliseconds since epoch plus current interval we also should write a function that kills all the enemies so when we start the game again we instantly kill the enemies so avoid kill all enemies will go access the game controller dot enemies which is the list of enemies dot for each enemy and then we'll set enemy dot is dead equal to true remember to import enemy and what this is doing is it's accessing the enemy list iterating over it and we set each enemy is dead to true and then the update function in our game controller removes all enemies that are dead so that's how we killed the enemies at the top of our initialize function let's just call the kill all enemies method now the last method we need in our enemy spawner is update and now we'll just taking TT as usual the first variable we have to create is called int now and we'll just set that to daytime now milliseconds since epoch next let's make a check for if game controller enemies dot length is less than the max amount of enemies we can have and the current time is greater than or equal to the next spawn so we check if we have the maximal enemies on screen already and if we don't then we also check if the current time is greater than our next spawn which means we can spawn a new enemy so we call a game controller dot spawn enemy which is the function we wrote before which spawns an enemy at the top right bottom or left each with a 25% chance to decrease the interval that enemy spawn at we can do another check so we check the current interval if it's greater than the min spawn interval so if the current interval is greater than 0.7 of a second then we want to take our current interval and subtract the interval change and we set our interval change to 3 then we also want to subtract the current interval by current interval times 0.1 so 1/10 of our current interval dot to int and this way our enemies will spawn faster outside of this block Oh F do is update our next bond and that'll speed now plus the current interval let's it safe and our enemy spawner is done so we cannot implement that into our game by creating the enemy spawner enemy spawner makes sure to import it call it enemy spawner inside our initialize function enemy spawner equals enemy spawner this and we don't need to call it in render because we're not rendering the enemy spawner anywhere on the screen we need to call it an update because that's where we're going to be dealing with the intervals so at the top of update we'll call enemy spawner dot update and passing T now let's hit save let's restart the app and we get the error that 4-h was called a null and this is PS enemy uses null at this time which means that back in our initialize function we have to make sure we create the enemy spawn or instance after our enemies list so we have a list to iterate over now we see that our enemy spawned here if we click three times enemy disappears and the enemies are spawning now and we see that enemies are spawning from all the sides so it's working and right now we have three six seven enemies and that's the max amount of enemies we wanted on the screen at one time now let's add the score dreary game so at the top let's add another variable called score and this score we're just gonna set to zero but we can also remove these spawn enemy right here inside initialize now we have to think about when we want our score to update and if you guys remember when we wrote our on top down inside enemy on top down we wrote score here in a comment and that's because we want to access our game controller dot score and just increment it by 1 because when an enemy dies we want our score to update so inside here if we just print game controller dot score it save let's hot restart the game and now when I click on an enemy we should see our score increment inside the console and we saw it flash for a second so to clean this up let's go to our player and remove the print current health and if we click on the enemies we see the score increasing it's four click kill another one it's five so our score is working fine for resetting the game inside our player dot dart all we have to do is call it game controller dot initialize and that's going to reset our whole game because the initialize function in here resets all of our instance variables back to their default values let's create a new component to render our score text on the screen that component will be called score underscore text dot dart and it'll be class score text final game controller game controller when we need to use a text painter and have an offset position make sure you import the game controller import painting and now for the constructor this game controller inside here we're going to define our painter so painter equals text painter we'll set the text aligned to text-align:center and then we also have to set the text direction text direction would be equal to ltr' because that's left to right and since this game is in English we read from left to right once it save on that I'm in position we can just set that to offset dot zero we also need to create the render method and that will take in a canvas for this we can just do painter paint and we paint the canvas at the offset position the last part of our score text is the update method and we need the update method so we can constantly check the score and update the score text accordingly so we're going to write an if statement and we're in do painter dot text and because painter dot text will not always have a value we can do an Ola where operator and if it's null then we set it to an empty string we say is not equal to game controller dot score not to string so this is doing is it's checking if the painter text is not equal to the current score then we want to update the score so painter text is equal to text ban text game controller dot score to string we also need to include a style and when you say textile color colors black font size and we'll set that to 70 point oh and we need to import material for the colors now we need to do painter that layout and this is going to get the visual position of the text so we know how wide it is and how tall it is and then we can set the position so a position will just be offset and that would be game controller dot screen size dot width divided by two and then the same thing we do with all components in this we subtract the painter width divided by 2 let's do the same thing for the screen size height replace with width height and instead of dividing by 2 for the height we can actually multiply by zero point two which would put the text right around here at point two of the height inside our game controller we can make the score text score text score text it save and then initialize score text is equal to score text this save and we also need to render it so let's render it right after the enemies so enemies will go underneath it score text dot renderer C and then the update we need to update it so score text update t let's it save I'll restart the app and now if I kill an enemy we see that these score increases and now the score is working fine and for now I'll just comment out the enemy spawner and tatra sort the app so let me stop spawning in order to implement the high-score feature in per game we need to go to our main dart and remember when we added the shared preferences package in the beginning of the tutorial we need to use that now so above our game controller we're going to write shared preferences and import the shared preferences dart storage equals oh wait shared preferences get instance so we're getting an instance of the storage and then we want to pass the storage instance into our game controller so we'll say storage there save that inside our game controller at the very top let's create final shared preferences called storage and then our game controller constructor will take in this dot storage it save and now we can use the storage variable in any of our components and the place we want to do it is back in our enemy dart right after we increment our or we want to do a check to compare the current score to our high score so we do if game controller dot score is greater than the game controller dot storage dot get int for high score and so if our high score is null which means that it's our first time playing and we never set a high score then we just want to assign zero to high score and so if our current score is greater than our high score and we just set the game controller dot storage dot set int high score and the value is just game controller dot score and that's how we set our new high score in order to show the high score on the screen we need to create another component but before we do that let's actually create a new file in our Lib directory called state dart state dart is going to be an enum state and it's going to have two different states menu and plane so our game will have two states one where we're in the main menu and we're not playing the game and once we tap then we change the state to playing and that's when our enemies will spawn inside the game controller we need to create state state and make sure to import the enum inside the initialize function we just need to set state equal to state dot menu because when we initialize the game we want the game to initially be in the main menu a state you know Millau us to check whether or not to render certain components on the screen or update certain components so inside our render method right after player dot render will check the state so state equals equals state menu so when the state is menu what do we want to render we want to render the start button and the high score text otherwise we want to render all of this and we can just put else here and I'll render this if the state is not a menu but if you guys ever want to add more states then you just do else--if state equals state playing and just do a check for it and that would work the same way inside our out date method we do the same check so state state menu else if state playing so we're playing the game then we want all this in there and don't forget the enemy spawner inside the menu state we just call start button not update and high-score text dot update and Freyr it'd be a render see render see so let's not restart the app and as you can see we're in the menu state right now because the enemies are not spawning we have no health bar and there's no score the way we want to be able to start the game though is by just clicking the screen so inside our void on tap down we can remove the print right here and we'll do another check if state is equal to state menu then we want to set the state equal to state a plane so the game starts otherwise if the state is equal to state dog playing then we wanted to do the check to see if we're clicking on enemies and if we click on an enemy then we want to damage them now if I click the screen we see that the game starts and we have the score up here and the bar down here and if I die then the game goes back to the main menu so we're almost done with our game all the functionality is working we just need to create the high score text here and the start button so inside components let's create a file called high score text dart and if we go to our score text let's just copy this whole entire file and paste it into high score text and change score to high score text and then the bulk of our change will be inside our update the first thing that's different is that we need to make an integer variable called high score and that will just be game controller dot storage dot get in high score and if there's no integer which means that we never actually played the game so there's no integer to save then we just set it to zero after that we don't need to check anymore so we can remove that if statement the painter text instead of doing game controller dot score dot to string we can change this to high score : and then use the dollar sign and put high score [Music] let's change the font size to 40 and that's pretty much it for our high score text game controller we'll add the high score text right here high score text I score text remember to initialize it and it takes this inside our render method let's uncomment the high score text render and our update let's uncomment ice core text I'll update it save let's hot restart the app and now we see our high score text appeared if we click to start and let's kill one enemy and then once we die we can see the high score update so I just looked at why our high score was not beating and it's because I forgot to add parentheses around the game controller that storage that get in inside our enemy door so make sure you guys add the parentheses here here's what was happening was that it was comparing to game controller that sorts I get in and since there was no value there it would not go into this block so again if you guys have the same error to make sure to add the parentheses right around this whole statement and then your high score will save the last thing we have to implement is the start button so inside components we can make something called start button dart class start button final a game controller game controller text painter painter offset position and I guess this is more of a start text than a button because we're displaying text down here so we can just change it to start text change this to start underscore text import material dart and then we'll make the constructor start text this stock game controller painter will be equal to text painter text align text align dot center text direction will be left to right because this game is in English and position will be offset dot zero and since we're basically writing the same thing as our high score text we can just go into here copy the render and update functions go back to our start text and its pop it in here let's change this update method here so we don't need the in high score etext will just be start and will make the font size 50 for the position of the star text will make it point 7 so it'll be right around here and then back in our game controller we can add start text start text and the usual now so start text equals start text this inside our render method will say start text dot render it save and then the update will be start text dot update let's hit save I'll restart the app so you stop beating these errors and now if we click start our game starts we can tap enemies three times to kill them and we see our score increasing and I'll keep going for a little bit just so we can see how many enemies will spawn and now we see that the enemies are spawning a lot faster so of course this games a lot easier on the phone because we can tap multiple enemies at the same time on the computer it's a bit hard but yeah that's the game congratulations on building your first floor game let me know in the comments below if you enjoyed this video and want me to build more games with flutter remember to leave a like subscribe share this video and to start up a story and get home thanks for watching and I'll see you in the next one [Music]
Info
Channel: Marcus Ng
Views: 68,500
Rating: 4.9513841 out of 5
Keywords: flutter, flutter apps from scratch, apps from scratch, flutter game dev, flutter game development, mobile game development, first flutter game, first mobile game, basic flutter game tutorial, flutter games, game development, flutter flame, flutter shared preferences, flutter save highscore, flutter spawn enemies, flutter gaming, flutter game app, flutter beginner game, flutter game tutorial, flutter mobile game, flutter basic game, flutter game, flutter game dev tutorial
Id: o_eVKOqY48Q
Channel Id: undefined
Length: 66min 17sec (3977 seconds)
Published: Sat Nov 09 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.