Quick start to building a game in Flutter

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[MUSIC PLAYING] FILIP HRACEK: Let me guess-- you want to build a game. Well, you're in the right place. In this video, I'll walk you through the process of getting from a game idea to a published indie game in Flutter. My name is Filip. Last year, I released a successful commercial game built in Flutter. This year, I built an open-source sample, which shows a game with all the bells and whistles, which means ads, in-app payments, achievements, leaderboards, main menu, settings, sound, music-- the works. And today, I'll show you a starter project that you can use to build your own game. I went through the pain of implementing all the bells and whistles so that you can focus on the meat-- the game itself. This is all part of the Flutter Casual Games Toolkit, which you can find on flutter.dev/games. Why would you want to build a game? Well, two reasons, really. First, let's be honest-- it's a lot more fun to be building a game than it is to be building an app, most of the time. But yeah. Second, games are kind of a big deal. They are. They make money. So according to some estimates, 70% of App Store revenue is coming from games. Only 30% is coming from apps. One way I like to categorize games is splitting them between app-like games and video games. Video games are the more stereotypical kinds of games-- arcades, shooters, racers, platformers, and so on. App-like games are things like board games, card games, visual novels, puzzle games, strategies, and so on. To be clear, I don't think any player makes this distinction between video games and app-like games, but from our point of view, it's really useful. Video games will typically repaint the screen every single frame. The player will continually apply some kind of input, like holding a button or a direction. App-like games are different. Their screen is mostly static-- not completely, of course, but mostly. Just like apps, they wait for the player to tap on things-- tap this button, tap this portrait, tap this building, whatever. These games don't need to be turn-based, they can be real-time, but the player controls them with app-like gestures. They feel like games, but technically speaking-- "technically speaking,"-- they're closer to apps. In this video, we'll be focusing on app-like games. Flutter is a-- mwah-- fantastic fit for these kinds of games. Flutter can make beautiful UIs. It gives you control over every single pixel. It is completely open-source. It is very cross-platform. It's fast, efficient, and it makes it easy to build app-like interfaces. App-like games are less stereotypically gamey, but they are insanely popular, especially on mobile, where you don't have these kinds of control devices, and instead, you have a touch screen and an often distracted player. Think of games like Puzzle and Dragons, Candy Crush, Coin Master, Gardenscapes, and the like. To be clear, most of what we'll be talking about today also applies to the more traditional video games in Flutter. Even with them, you need a main menu, a settings page, some kind of monetization, and stuff like that. If you want to build a video game in Flutter, there's the Flame Engine. It has been made and optimized for these kinds of games, and it's behind some very successful titles. Flame Engine gives you a game widget, which is-- you guessed it-- a widget, which means it plays well with the rest of Flutter, and therefore with everything that I'll be talking about today. OK, let's have a look at some actual code, shall we? This is the game that I made this year. You can check it out in the usual stores. The audio effects are by me. FILIP HRACEK (VOICEOVER): Swish, swish. FILIP HRACEK: But more importantly than in the app stores, you can also read the code on GitHub. Link in the description below. This game is built on top of the template that we'll be covering today. So if you want to see more real-world examples of how you would implement things on top of this template, you know where to go. You may also find it useful to check how I made some of the visual stuff like the custom transitions, like the little pop of the restart button, or the roughly drawn lines. These little things really help sell your game as an experience. They make your game feel like a game. But that's a full game. You probably don't want to work on someone else's game, you want to build your own. For that we have the template. It's like the Flutter create project, except it's for games. And it has all the bells and whistles like the main menu, sound, music, in-app payments, and stuff like that. It looks a lot more basic than even the tic-tac-toe game, and that's by design. You want to add your own styling. You want to make it your own. I don't know how your dream game should look like. It also doesn't have any actual game. That's also by design. That's for you to build. You can, of course, start your game with the usual counter template, but sooner or later, if you want to put your game out there, you'll want all those bells and whistles. Before we look at the separate features, I want to take a general look at the template and the approach I took with it. Because the template is doing so much, I had to be pretty opinionated. I had to take an approach and stick to it. I had to pick packages too. I couldn't be completely tech agnostic. For example, for accessing services such as audio, I chose to provide a package. It's low-level, it's easy to understand, and it works with pretty much all the other approaches out there. For the game itself, you can, of course, use whatever approach you like best. The game template itself has no opinion on how you implement your game. It's also just the starter template. If you feel strongly about using something else to, say, play audio, then you can totally change the code. My goal wasn't to create the game engine to end all game engines. My goal was to give you a quick, comfortable start and to get out of your way as much as possible. When building any kind of app, there is a trade-off between robustness and speed of development. When it comes to games, the scales tip quite a little bit in favor of speed and experimentation. Games typically don't have that many layers of indirection. They also don't have the kind of test coverage that many apps do. Games are usually simulations of some kind, and rely on massive amounts of shared state, which is hard to meaningfully mock up and test in isolation. Plus, with the game, you need to build an insane amount of features very fast, and then you will delete half of those features and try something else. In other words, you will write a lot of throwaway code because you cannot know what will be fun in advance. There's a bit less need for robustness too. If you crash a game, it's not like someone's losing their accounting data-- unless your game is about accounting, but that still doesn't count because those are not real accounting data, so you're fine. Game programming is just a lot more by the seat of your pants. A lot more cowboy programming in the game development world compared to the app world, especially if you're a solo developer, but also in the big studios. That's not to say that you should just give up on code quality here-- far from it. Great games are built with great engineering. Just remember that you're not building accounting software here. This is why the code structure is quite shallow in this template. If you want to play a sound, just get the instance of audio controller and call play sound directly. I could, of course, make it so that it's using some kind of publisher-subscriber pattern, but I am not convinced that the increased complexity of the code and indirectness of the code would be worthwhile. That said, if you want to see a more robust game code in Flutter with test coverage and such, Very Good Ventures just released a pinball game made in Flutter and Flame, and the GitHub repo is in the description below. All right, let's get to the code. Let's start with the pubspec.yaml file just so you can see the dependencies. All right, so we are using-- so these I call the core dependencies, I guess, because they kind of must be there for everything to function. audioplayers is how we play sound and music. cupertino_icons are there in case you want to add Apple-like icons into your settings menu, for example. go_router is there to route things-- the navigator, really. logging is there so that it's easier to log things. provider, shared_preferences-- that's the basics, right? And then there are three other dependencies. game_services is there for achievements and leaderboards, google_mobile_ads for ads, and in_app_purchase for in-app purchase. And I say here if you know that you don't need, for example, in-app purchases, you can just delete this dependency and then get rid of the files that actually use that dependency, and it's all good. I also show how to obviously use assets, how to use fonts, and how to create a Flutter icon because that's also a big part of having a game is to have a good-looking icon. So I'm using the Flutter icons package to create the icons for both iOS and Android. All right, let's look at the star of the show, and that is main.dart. main.dart starts with logging, right? So this is the easiest way to do logging in Flutter, and it's basically if you set this up, and you're using the logging package that comes with Dart itself-- as in, like, the Dart team is working on that package-- then you can just add these few lines, and then you can do whatever you want with logs that come from anywhere in your app, plus anywhere in any packages that are using the logging package. So this is nice. Right now, I'm actually making this video quite a few weeks before when I need to release the code. I think by the time that you see this code, it will actually maybe send things to Crashlytics or something like that. But it's not a big change. You can imagine how you could just take this record, which has things like the message and time and where the message is coming from, and either put it into memory or just print it to the Console or whatever else. Cool. Then we go full screen, because that's what games often do. So we are using the edge-to-edge system UI mode, which is not completely full screen. It still gives people, I think, the top bar. So you could change it to something else, but that's how you go full screen. And then there are these three blocks of code that are mostly commented out at start, and these are commented out because they need some kind of setup on your part before you can meaningfully use them. So for example, if you want to have game services, as in like, you want to have the ability to give people achievements, award players achievements, then you need to go to Google Play Console and then add achievements there. And then you also need to go to the App Store Connect and add achievements there. And after that, you can go and uncomment this code and do whatever you need to do, but not before you are actually ready to do that. So that's why these exist here, and that's why they are null at start. They are commented out. Here you can see how it's used. So my app, which is the app, the game, starts with some dependencies that are injected to it-- the local storage settings, persistence, where do we put the settings, where do we save the player's progress? But then there are these three controllers-- in-app purchase, ads, and game services-- and if they are null, then the template is smart enough to not even try to do anything with these integrations. And so let's go a little bit further down. The MyApp is actually just the normal MyApp widget with go_router routes, so this is where you would add more routes if you need them. But at this point, you have the main menu, of course. You have the level selection screen, which in your case could be a map. I don't know. It could be anything. Then there is the actual PlaySession, which could be-- well, again, anything. That's probably where people will spend most of the time. And then there is the win screen or something that we show to the player when they have successfully finished part of your game. And in this case-- well, I'll show you later, but it shows ads and score, and it does some things like that. And then we have settings. Then we basically just have the AppLifecycleObserver, which I will go to later, but it has a MultiProvider, and this is where everything that you need is provided to you anywhere in your app via the provider package. And then it's just a Flutter Demo and MaterialApp using the router that we defined above, and with a little bit of theming, and that's it. Now let's look at the source of the actual different features. So I told you it's a shallow structure. It's basically just all the features that we have in the game, and they all have their own little directory in source, and that contains both the widgets and everything else that you need for these things. So in ads, the star of the show here is the AdsController, which is just a class that is, again, provided to the rest of the game, the rest of the app, via a provider unless you haven't set it up, in which case it's null. And the AdsController does things like initializes, it preloads an ad that is very important. As I learned, if you don't preload ads, then they might take, maybe, like, 3 seconds to actually show up after you show them via the normal non-preloaded widget, and that's not good because it takes way too much time. So sometimes 3 seconds-- the player is already somewhere else. So you want to show the ad exactly at the time where you actually want to show the ad, so that's why we have a preloadAd. And that's it. That's the AdsController. And then we have a widget that you can use to show the ad itself so that when you change the orientation, it's still works, and so on and so forth. So this is just a little bit of extra things around the ads package. AppLifecycle is really nice. Now we actually only use it for the sound, but you might be using it for something else. This is just so that if you put it in here, as it is put here, it will provide another-- not ChangeNotifier, but it will provide a ValueNotifier of lifecycle. And then you can listen to this lifecycle, and as you will see in audio, you can react to those lifecycle changes. So you can say, oh, you know what? I want to pause the audio when people put my game into the background. Well, it's something that is already implemented for you, but you might do something else. You might be saving something somewhere when people put your game into the background, or similar things. So that's why it's there. But for the most part, you probably don't need to touch this. AudioController is where we are using the audio player's plug-in. It has a music cache and a sound effects cache. The sound effects cache is more important because it caches, at first, all the sound effects that you put to it, and therefore, it immediately plays them when you need them to, right? It doesn't need to load them up, so that's nice. And again, you can, of course, change any of the code here, but most of the things here are just it listens to the lifecycle modifier, which means that it will stopAllSound, for example, when the state is detached. It also listens to the settings, which we haven't come to yet, but if the settings change so that, for example, a player turned the sound off or muted the whole thing, then this will listen to it. It will not play any sound. It will stop music and so on. And then we have dispose or initialize, which as I told you before, it will go through the sounds and cache them. And then you have the playSfx method, which basically plays the sound effects. If you want to know what sound effects are available, again, this is just using these assets that I have in assets/ sound effects. These are all public domain samples. You can use them, but of course you'll probably want to use something else because these are something that I made with my mouth. But the way I did this is you probably don't want to call AudioController with an actual name of some MP3 file, you want to call it with just sound effect type. And here are just a few. And you can, of course, add more, remove. And then you add a list of the MP3 files or whatever OGG files that you want to play. The reason there is a list and not just one is because it is a good practice, and it makes your game much nicer to play when the sound effect for one action is not always exactly the same sound. It gets very tiring to be listening to the exact same sound all again and again, right? So I went a little bit overboard with this, but if you have, for example, buttonTap, and you have maybe two, three, four sounds that are very similar but not exactly the same, it will make your game sound much better. OK, so we have these-- that's the sounds-- and then we have songs, which is just a little class that, as you can see, we have only one author, Mr. Smith. Thank you for providing the music. It's Creative Commons, attribution-style license. And three of those songs are included in the repository so you can start immediately with something in the background. That also makes a huge amount of difference, to add some kind of music into your game. Again, games are cultural artifacts. They often give you some emotions. That's why you want music there. Cool. So that is the audio. Then we have game_internals. In our case, that's where, basically, you add maybe the AI, anything that isn't really anyhow connected to Flutter itself. Of course, you can put it anywhere else, but that's where I would put it. And this could even be just an import from some other package. You could have a completely pure Dart, non-Flutter package with the game internals, and then you can just import it over here. In our case, because this is the game template, it is only has a goal, which is a number, and then a progress, which is also a number. And then if we evaluate the level, if the progress is bigger than the goal, then we call onWin. This is just one of a billion ways to make something like this. Obviously I'm not telling you to use a changeNotifier and this kind of thing to make your game. It's just a sample. Then there's games_services. So that is how you add achievements and also put things into the leaderboard. And that's also pretty straightforward. Basically, the only reason I have it like this is so that you can mock it and you can maybe test it better. But basically, this just goes and uses the games_services package and uses the static methods there, but nothing too crazy. So awardAchievement is just GameServices.unlock basically. Then there is the initialize, showAchievements, showLeaderboard, submitLeaderboardScore. And here, you will want to probably go here and maybe change how the score is computed. This is over here. This file has a class called Score, and it will let you create a score. In my case or in the template basic case, you give it a level, a difficulty, and a duration, and it will compute some kind of number, which is the score. And so we'll get to that later, but basically, then if you submit leaderboard score, you give it the score over here, and that score already has an integer, which is what the leaderboards actually want. They only want an integer. They can't get any other metadata from you. So in this case, it's just that. In some games you might want to have more than one leaderboard. Like for example, oh, here's a leaderboard of how fast people did the first level, and here's the leaderboard how fast people went through the whole game. And for that, you would want to add a new method here that uses some other thing, some other leaderboard ID. These leaderboard IDs-- you go and you do them, or you get them from App Store Connect and from Google Play store. After games_services. We have in_app_purchase. In_app_purchase, again, is just controller, and it's very simple, I guess, wrapper around the in_app_purchase package. in_app_purchase package provides a single purchase stream, and then you listen to it, and that purchase stream gives you all the data that you might need. It gives you all the updates that come from the in-app capabilities of the phones. So this kind of makes it a little more usable because you just call restorePurchases at the start of the game so that you know what has been actually purchased. Then you have things like buy, which just buys something, right? And so on and so forth. In our case, all that is implemented is just one purchase, and that purchase is the "remove ads." Which of course needs to be first set up in App Store Connect and in Google Play, but after that, you can just use it. So that's ad removal, which is this. Next up, let's have a look at the level of selection screen, which is, I guess, the first screen that we're actually looking at. So let's have a look at the actual game. This is how the level selection screen looks like running on Mac OS. And it's just a widget, right? It's just a screen with a scaffold and all that. And here, I'm just showing you how you might implement something like this if it's only a list of levels. Of course, a lot of games will have something more interesting like a map or, I don't know, a grid or something like this. But if it's the list of levels, you might just start with this. And it just goes to the route of that session-- I mean the play level, basically, and that's that. Very, very short amount of code. And the levels, again, in my case are pretty straightforward. It's just a class that has things like the level number, the difficulty, and associated achievements. And, again, this will be something that you'll almost definitely want to change to your liking. So that's the level selection screen. Now the hero-- main menu screen. All right, so main menu screen looks in the game template like this. And it has some hero image at the start, which is just a text. Then it has the play button, which probably should be a lot bigger, but again, I'm not styling anything here. And then you'll see how I'm checking if gamesServicesController is null. I'm getting gamesServicesController here using provider. And if it's null, then we don't show anything between play and settings, but if it's not null, then we are showing these elevated buttons that are actually showing achievements and showing the leaderboard. And these things, by the way, they are implemented using the platform services that provide these achievements and leaderboards. So this just calls something somewhere, and it doesn't add anything into your Flutter app itself. So the achievements and leaderboards are overlays of the native platforms over your app, right? So it really is kind of far and forget-- just show achievements, and that's it. And when the player closes that overlay, they go back to playing your game. In this case, to the main screen. So this is very simple. And then there is the settings, and then there is this button, which is pretty important to have, I think, if you have music in your game-- and you should. You should probably make it very easy on the start page or on the main screen of your game to immediately mute everything. So you go and, of course, go to settings and see if you want sound effects or music, but you also want a mute button here just so people can kind of panicly immediately turn it off. And then there's a little thing that gives credit to Mr. Smith. All right, so that's the main menu screen. Let's have a look at the play_session. In our case, that's also super-- I mean, just so you know, the play session in the game template looks like this. It's just a slider, and it just tells you, hey, if you put the slider to 5% or above, you win this level, basically, right? So you can do that and then-- FILIP HRACEK (VOICEOVER): Yay. FILIP HRACEK: I still love the sound effects. And you get to the win screen, which we'll cover later. So let's have a look at level 2. It's harder, much harder, because you have to drag the slider all over to 42% and above. So that's what the play session screen looks like. The reason it's not just a button, or the reason I even included in the game template is to show how you might want to do the celebration, for example. This is done using a stack. Then also, I am showing how you can see when the player started that particular session so later you can check how long it took them to finish it. And we also see do we have in-app purchases? If so, do we have adRemoval in-app purchase active? And if not, if ads are not removed or if we don't have InAppPurchaseController at all, then we ask the adsController to please preload an ad to be shown in the win screen. So that's how you would do it. And again, this is fine. If you don't have in-app purchases or ads yet set up, then this will just not do anything, so that's fine. All right, playerWon is what the level state is calling when the player has won that particular level, and that does things like it creates the score using the length of play and the difficulty of the level and also the number of the level, and then it tells player progress, which we haven't gone to yet. How far the player has gone? Like, the player has finished level number this. And then there's a little celebration going on. We also play a sound that's the "yay." And that's how you play sounds-- you just do read AudioController. That is always there, so it's never null, right? You will need the audio controller for the game. And then you'll play a sound effect, and here, it's the congrats sound effect. Then, again, we'll find out if we have gamesServicesController, and if we do, then we put an achievement. Again, if the level has some kind of an achievement, then we send the achievement to the underlying system, and then we also submit the score to a leaderboard. And that's it. And then we go to the play/won or the win game screen. Next up, player progress. That's not a screen, that's just a persistent class that can save itself, and that in our case just saves the highest level reached so that if the player goes to the level selection screen, only the levels that they have already finished or the one that is just above that are shown. So that's what the player progress does, and all it does is it uses some kind of persistence_store to save and then load the highest level reached. Of course, player progress in different games looks differently. It could be the highest level reached. It could be just a set of levels that were successfully finished. It could be much more. It could be the score of each level. It could be the player's characteristics, like in a role-playing game, and so on and so forth. So this is where we persist this. And by default, the game will put all of this into the local storage, but we also have a MemoryOnlyPlayer ProgressPersistence that is especially nice for testing. Settings-- well, settings is this page, which you can access from here or from the play page here. And it has a list of things that you can change. So the screen itself is pretty straightforward. It's just the list view, basically, and with lines in it, right? So that's nothing that you can do yourself in 5 seconds-- maybe 5 minutes, OK? But it also has SettingsController, and the SettingsController has ValueNotifiers with like, muted and soundsOn and playerName so that you can kind of play around with this. And the soundsOn, musicOn, and muted are all synced with-- or the audio controller listens to these and will change its behavior according to that. So you can just change the value of soundsOn, and automatically everything will just work. So that's toggleMusicOn, toggleMuted, and so on and so forth. And because these are value notifiers, you can actually listen to them, and so you can also update your UI easily. There is a CustomNameDialogue just in case you want to-- in games, often there are places where people can input names or input some string, so this is just showing how you might want to do that, but it's not a big deal. And again, there is a persistence store for settings. This could be something different than the player progress, right? So settings should probably go to the local storage for sure, but the player progress in some games might go to some other like, cloud storage or something like that, so that's why it's different and separate. Style is where I put things like the transition that looks like this. Not this one, but this one where it kind of slides. The only reason, again, is so that it's obvious where to put these things. The buildMyTransition is used from main.dart so that it's obvious how you might want to do it, but it's not required, for sure. Palette is a class that just has the palette that I found somewhere that's good for games, and we'll get to where to get good color palettes later. And you could, of course, try to use something like material theme, but I find that games generally have a lot more colors than apps, and you want some kind of place to put all the colors in one place, and so that's why I created this palette class. You don't need to use it, but I find it nice to have that. That's the responsive screen. It just makes it a lot easier to create a responsive game or screen with things like a menu on the side but a big part of the screen taken by something big, like the list of levels. Again, it's just style. It's just like widgets. And then there's this SnackBar if you want to show a snack bar, Again, just a little helper. And then the last is the win screen. Let's win a game. So I need to drag this over to here. And yay, I won. You won. The thing here is that if you have ads enabled and the player hasn't bought the ad removal in-app purchase, or there are no in-app purchases in the game, then we can show a banner, and that banner will automatically use the preloaded banner if it's available from the ads controller. And then it just shows you won and a few things like score and time, and that's it. You just go to continue. All right, that's the Dart code, but let's have a look at assets as well. So assets in games are probably more important than in apps even, because games are just more artsy than most apps. So a good thing to look at is obviously where to find assets. There are some included in the template, but it's way less than you will need in the end. You have some things that I drew myself, like the back button, the restart button, the settings button. There's the music, but only three pretty short tracks. It's really good music for mobile games because it sounds well even if you're not using headphones. But again, you might want to look at other places. And then there is the sound effects, which you probably almost definitely want to replace with something more professional than my mouth. OK, so where do you find these? Well, there are a bunch of places all over the internet that have assets. I will try to put all of these into the description below, but I think there is a limit to how many URLs there can be, so take care of what I show you. There's itch.io/game-assets. Many of these assets are free. Some of them are very, very reasonably priced, like $2 or $5. Some of them are a lot more expensive, but it depends on your budget and how much you want to invest in your game, obviously. So itch.io/game-assets. There is the graphicriver/game-assets, which has a bunch more. And these are often just PNG files that you go through and then put into your asset directory and just use them in Flutter. So there's nothing here that's not usable in Flutter. There is the Game Dev Market-- again, a bunch of assets of different themes. There is opengameart.org, which is, I think, all free and all very like, licensed with public domain and stuff like this. It was pretty hard to find good assets here, but it's a good start. As you can see, I'm talking about assets, and mostly we're looking at pictures, but there's also music and sound effects. So take care of that. Craft Picks is another one, another asset store with pretty good assets that you can use. And then a Humble Bundle often has bundles which are a bunch of different asset packs put together with a very reasonable price. And you actually give some money to charity if you buy through Humble Bundle. So this is just what's currently available, but generally speaking, there's more. So Humble Bundle is nice. Then there's the Art Breeder, which is nice because it basically lets you combine a picture and a photo into something completely new using AI. And of course, then you can create your assets of your own. Just know that it's really hard. It's really hard. It's good to start with some kind of a palette, so I'm looking at lospec.com, which has a bunch of palettes somewhere in your palette list. And if you go there, you can just start with something that you like here, and stick to this. Let's say you say, OK, I want to use this. Stick to just these colors, and then your game will look like it's a piece of art instead of just everything is different, right? This is a big part of making your game look like an artifact and not just a bunch of different assets from different places. You can create your sprites, especially if you're into pixelated animation and stuff like this. This is Aseprite, which is for free if you download and build it yourself, or you can buy it if you want to support the developer and also save some time, because you can then just download it and not build it. And there are other things like Affinity Photo, Affinity Designer, Photoshop, and other software where you can, of course, create your assets. Just know that when you draw your own assets, you must have a lot of time or you must make your art in the game very, very simple-- and often, both. You still need a lot of time to make it simple. Think about Minecraft. That's very simple, right? Considering that it's a 3D game, the art there is simple and pixelated, but it still took the creator a bunch of time, I'm sure, to come up with all that and make it work nicely. If you don't want to create your own assets, and if you still want to have something more custom than what you will find in the asset stores, you're going to have to go shopping for an artist. And that is either you're very lucky and you have a friend or, I don't know, a brother or sister who can create art for you, which is fantastic. But if not, then you're going to have to go to the market. And one way to go to the market is to go to a place like fiverr.com or upwork.com and just look at their talent. They have, often, people who do art, and you for a very reasonable price, you can ask them to create some art for you. So that's Fiverr and Upwork. Of course, you can go more into the art place, like, for example, ArtStation, where you literally have people who create amazing art. And some of them take commissions, which means you can ask them to do something for them for money. And then there's the Rive community, which is something also very similar. And it's not only static art, but also actual animations. And the good news is that Rive runs as a runtime in Flutter, so it's not a GIF or anything like this, it's an actual canvas animation that you can use. So that's that. Then you can just look into-- in my case, for my award-winning game, I went and look into books, and I found an amazing artist. And I just wrote them an email and said, hey, do you want to maybe make art for my game? And they said yes, and that was amazing. But again, this takes time. It takes money. It's not easy. In short, assets are a big part of game development, whether you like it or not. And so if you want your game to have a lasting impact, and if you want people to talk about your game and get back to your game, you have to invest the time and sometimes money to make the art good. And I'm not just talking about the art as in the pixels on the screen, but also the sound and also the music. So there you have it. The next time you have an idea for a mobile game, you don't need to start from scratch. You can start from the template. And you can get inspired by the game sample. And your game will come with all the bells and whistles that a "real game" should have, like the main menu, settings, audio, and potentially achievements, leaderboards, ads, in-app payments, and more. Look-- making games is hard, but it's also rewarding. Games are experience machines. They are part of culture. They don't only entertain, they can also have a message. They can teach us something. And I would love to see a lot more games from a wider variety of game creators. And you may be one of them. Don't forget to check out the Flutter Casual Games Toolkit at flutter.devs/games, and good luck.
Info
Channel: Flutter
Views: 221,142
Rating: undefined out of 5
Keywords:
Id: zGgeBNiRy-8
Channel Id: undefined
Length: 53min 46sec (3226 seconds)
Published: Thu May 19 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.