POKEMON • FLUTTER GAME FROM SCRATCH
Building a Pokémon Game with Flutter
Introduction to the Project
- The speaker introduces a new project for 2021, focusing on building a Pokémon game from scratch using Flutter. This project aims to evoke nostalgia and enhance understanding of the Flutter framework and Dart language.
- The speaker expresses hope that this tutorial will provide educational value or inspiration, especially for beginner coders facing challenges in learning programming.
Setting Up the Flutter App
- The development begins by creating a new Flutter app, where the speaker deletes existing code to start fresh. A stateless widget is created as the foundation of the app.
- The speaker configures the MaterialApp settings, including disabling the debug banner and setting up a home page with a stateful widget called HomePage.
Designing the Game Layout
- The layout design is inspired by classic Game Boy aesthetics, featuring controls at the bottom and gameplay on top. A column widget is used to structure these elements.
- To achieve an appropriate screen division, expanded widgets are utilized; however, an aspect ratio widget is introduced for maintaining a square shape for gameplay.
Implementing Aspect Ratio and UI Elements
- An explanation of aspect ratio highlights its importance in defining width-to-height relationships; specifically aiming for a 1:1 ratio for square gameplay.
- The top section's color scheme is adjusted to black with dark gray text added to enhance visibility. Branding elements like "Game Boy" and creator credits are included in this section.
Adding Buttons and Interactivity
- Padding adjustments are made to improve layout spacing. Text styles are modified for better readability against background colors.
- A button class is introduced that accepts text and functions as parameters. This class will be used later in creating interactive buttons within the game interface.
Finalizing Button Functionality
Game Development UI Design
Designing the Layout with Rows and Columns
- The speaker discusses the need for arrows (up, left, down, right) in the layout and mentions using rows and columns to achieve a crude design.
- A grid view builder is considered but ultimately dismissed in favor of simpler rows and columns for this project.
- The initial layout consists of grids where directional buttons will be placed, eliminating unnecessary individual buttons from the middle section.
- A blank container is created to remove unwanted elements from the interface, ensuring a cleaner look.
- Main axis alignment is adjusted to space elements evenly within the row.
Implementing Arrow Buttons
- The speaker replaces placeholder text with actual arrow symbols representing directions (up, left, right, down).
- Adjustments are made to ensure that button placements reflect a staggered diagonal movement similar to classic game controllers.
Creating Button Functionality
- Additional rows and columns are introduced to create mini grids for button arrangements while maintaining simplicity over complexity.
- The speaker outlines plans for creating methods corresponding to each button's function (move left, move up, move down).
Finalizing UI Elements
- Functions are defined for each action button: moving up/down/left/right and pressing 'A' or 'B'.
- Visual improvements are planned for the Game Boy interface by changing color schemes.
Incorporating Sprites into Game Design
- The next step involves downloading sprites from online resources; sprites are collections of images used in games.
- Specific examples of sprite sheets related to Pokémon games are mentioned as sources for graphics needed in this project.
Utilizing Resources Effectively
- Instructions on cropping downloaded sprite sheets into usable files highlight practical steps in preparing assets for game development.
Setting Up Image Assets in Flutter
Adding Images to the Project
- Navigate to your project folder and locate the app's library. Create an "images" folder within it for storing image assets.
- Update the
pubspec.yamlfile by uncommenting the assets section under Flutter, specifying the path aslibrary/images/. This allows Flutter to recognize and include these images in your project.
Creating a New Folder for Maps
- Create a new folder named "maps" within your project structure to organize map-related files.
- Inside this maps folder, create a file called
little_root.dart, which will define a stateless widget named LittleRoot.
Defining Coordinates and Current Map
Setting Up Widget Parameters
- The LittleRoot widget will accept three parameters: x-coordinate, y-coordinate, and current map name. These are essential for positioning on-screen elements accurately.
- If the current map is set to LittleRoot, return an image asset located at
library/images/littleroot.png. Ensure that the string value matches the exact path of your image.
Implementing Stack Widget
- In your main file, utilize a Stack widget to layer multiple widgets on top of each other. Begin by adding LittleRoot as one of its children.
- Import necessary files if they do not automatically import. Set initial values for x and y coordinates (e.g., zero), along with naming the current map as "little root".
Understanding Coordinate System
Coordinate Values Explained
- The coordinate system ranges from -1 (left/bottom), through 0 (center), to +1 (right/top). Adjusting these values shifts elements accordingly on both axes.
- Instead of hardcoding coordinates directly into functions, create variables like
mapXandmapYfor flexibility in changing positions dynamically.
Creating Character Representation
Defining Character Properties
- Introduce another folder named "characters" where you will create a file called
boy.dart. This file will represent character properties using a stateless widget called MyBoy.
- Set up an initial container height of 50 pixels for visual representation. Use an image asset representing the boy character facing downwards (
boy_down_0.png) with appropriate fitting options.
Integrating Character into Main File
- Add MyBoy as a child within the stack in your main layout. Ensure proper imports are made so that there are no errors during compilation.
Movement Mechanics in Game Development
Setting Up Movement Coordinates
- The speaker discusses arranging the character's position on a grid, emphasizing the need for proper alignment to facilitate movement.
- To move the character up, the coordinates (map x and map y) are adjusted. The speaker uses a random increment of 0.2 for demonstration purposes.
- The notation used for adjusting coordinates is explained as shorthand; moving up decreases map y by 0.2 while moving down increases it.
Implementing Directional Movement
- Moving left and right involves changing x-coordinates, with one direction requiring a negative adjustment to reflect movement accurately.
- The current implementation results in unnatural movement since the character faces downward continuously; sprites are introduced to animate different directions.
Sprite Animation Logic
- Each sprite represents different states of motion: stationary (zero), mid-walk (one), and full walk (two). Cycling through these creates an animation effect.
- The code is modified to accommodate multiple sprites based on direction and walking state, ensuring that animations correspond correctly with movements.
Passing Information Between Functions
- In the main function, information such as direction and sprite count needs to be passed into the boy file for accurate rendering of animations.
- String concatenation is utilized to create dynamic file names based on direction and sprite count, ensuring correct image loading.
Initializing Character State Variables
- Variables are established for current location, sprite count (ranging from zero to two), and direction. Default values are set at game start: standing still with a downward facing direction.
- As directional inputs are received (up, down, left, right), corresponding changes are made to
boyDirection, which influences how the character faces during gameplay.
Testing Movement Functionality
- After implementing changes, testing confirms that the character now faces appropriate directions when moving; however, further improvements in natural movement animation are needed.
Animating a Character Walk Cycle
Implementing a Timer for Animation
- The speaker introduces the use of timers in their application, explaining that every 50 milliseconds, the state will be updated to increment the boy sprite count.
- It is emphasized that the sprite count should reset to zero after reaching three, preventing continuous counting beyond available sprites.
Fine-Tuning Movement Mechanics
- The speaker discusses adjusting movement speed from an arbitrary value (0.2) to a more precise one, aiming for realistic character movement in relation to game elements.
- A new variable called "steps" is introduced to streamline adjustments across multiple instances in the code.
Setting Up Game Coordinates
- The speaker identifies specific coordinates (0.65) for positioning the character correctly in front of a house within the game environment.
- They express concern about characters moving off-screen and propose implementing barriers to restrict movement.
Creating Barriers: No Man's Land
- A list named "no man's land" is created to define areas where characters cannot walk through, enhancing gameplay realism.
- The list will consist of pairs of coordinates representing restricted areas rather than single values.
Debugging and Validating Movement
- As part of debugging, coordinates are printed during character movement to track position changes effectively.
- This tracking helps identify desired starting positions and ensures players do not move into restricted areas like signs or walls.
Implementing Movement Restrictions
- A boolean function checks if a player can move into specified coordinates based on the no man's land list.
Creating a Game Map with Restricted Areas
Defining Walkable Coordinates
- The speaker discusses the concept of "no man's land" and how to create a list of coordinates that players cannot traverse. This involves identifying walls and houses in the game environment.
- A demonstration is provided where the coordinates are saved, ensuring that players cannot walk through designated buildings or walls.
Entering Specific Locations
- The focus shifts to entering specific locations, such as the "pokey lab." The player must be positioned at a specific coordinate (the door) to change maps.
- Upon reaching the door's coordinate, the map will switch to the pokey lab when an up arrow is pressed, indicating a unique entry mechanism.
Implementing Map Changes
- The speaker explains creating variables for managing map transitions, specifically for entering the pokey lab using defined coordinates.
- Code logic is introduced: if a player stands on a specific coordinate (0.625, -1.1), their current location changes from "little root" to "pokey lab."
Managing Current Location States
- New files are created for different maps (e.g., pokeylab.dart), which will handle rendering based on current coordinates and states.
- Importance of tracking current locations is emphasized; if not at little root or another specified area, it returns a blank container instead of displaying incorrect information.
Automating Movement Restrictions
- Similarities between code for different areas (like pokey lab and little route) are noted. Automation in determining barriers is discussed but acknowledged as complex due to unique room designs.
- A function is proposed that can check movement permissions against lists of restricted coordinates based on player direction.
Adding Characters and Interactions
Introducing Professor Oak
- Plans are made to add Professor Oak as an interactive character within the game environment, similar to previously implemented characters.
Character Interaction Mechanics
- A new file named oak.dart will be created for Professor Oak's character attributes including position and facing direction during interactions with players.
Enhancing User Experience
Image Cropping and UI Integration
Importance of Image Dimensions
- When cropping images, it's crucial to maintain the same dimensions as the reference image (e.g., Professor Oak's image should match the size of the little root image).
- The square dimensions are essential for maintaining proportionality when shifting maps; this ensures that all elements fit cohesively within the game environment.
Adding Characters to the Game
- To integrate Professor Oak into the user interface, import his file and place him correctly in the scene.
- After positioning, add his coordinates to a designated "no man's land" area to prevent player interaction with him, treating him like any other barrier.
Conversation Mechanics and Battle System
Conversation Implementation
- The tutorial aims to keep sessions under an hour while covering conversation mechanics briefly before concluding.
Battle Animation and Mechanics
- Animated containers were used for entering Pokémon into battle, mimicking actual game dynamics with specified durations for animations.
- A simple battle menu allows players to choose between running or fighting; only one move can be executed until a Pokémon faints.
Project Structure Overview
File Organization
- The project includes various folders: characters (including boy character, Charmander, Professor Eric, Pikachu), images (sprites and maps), and utilities (chat bubbles, health bars).