The game loop iterates over game entities and executes the update()
methods in each. This is where you update entity and component state, and render any components that need rendering (by calling component update()
and/or render()
methods). Seconds since the last update is found in Time.deltaTime
.
The class Game
is a singleton that gets instantiated on the first reference to it. The singleton is always available as Game()
.
Game().widget
is a reference to the game widget. runApp()
will run a widget and attach it to the screen. Thus, runApp(Game().widget)
will start the game engine.
This is the recommended sequence of code to start a game (the rest will be explained below):
import 'package:pogo/game_engine.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized(); // required
await Screen.setFullScreen(); // mobile - not for web app use
await Screen.setPortrait(); // mobile - not for web app use
Camera.size = Size(135, 240); // default is native resolution
System.defaultPivot = Pivot.topLeft; // default default is center
System.defaultPaint.isAntiAlias = false; // low-res games will want this
GestureInitializer.detectTaps = true;
GestureInitializer.detectPans = true;
await Assets.audioCache.load("explosion.mp3"); // not for web app use
await Assets.rasterCache.load("background.png");
await Assets.svgCache.loadAll(["enemy.svg", "player.svg"], scale: 0.75);
runApp(Game().widget); // required
await Screen.waitForStartupSizing(); // required
MainEntity(); // you can name your startup entity whatever you like
}
class MainEntity extends GameEntity {
MainEntity() {}
}
Line by line:
WidgetsFlutterBinding.ensureInitialized()
is required as the first line if you want to call setup features like Screen.setFullScreen()
before you call runApp()
.
The Screen
static class contains some setup functions.
The Camera
static class contains the main camera settings in case you need a scaled camera and/or panning. This is a good place to set camera size/scale, if needed for your game.
The System
static class contains the default Pivot and Paint settings.
The GestureInitializer
static class contains flags for setting up the main GestureDetector
in the game engine. You must initialize all gestures here that will be used anywhere in your game.
The Assets
static class contains caches for some assets. It is recommended to cache your assets (the ones that currently can be cached). It is not required to cache them in your main()
but this is a good place to do it for simple games. More complex games will want to use the cache features to load and clear assets.
Screen.waitForStartupSizing()
is the current recommended way to allow Flutter time to startup and size the game widget. This also sets Screen.size
for the first time.
runApp(Game().widget)
starts the game engine.
At this point, you can now call and instantiate your first game entity (called MainEntity()
in this example).
Debug mode can be turned on with Game().debugMode = true
. This enables FPS calculating with Game().fps(frameSpan)
. This also turns on some extra visualizations for game entities. Some components may also provide extra visualizations.
See the debug example app.
//TODO
Because a Pogo game is a widget itself, it is possible to use Flutter widgets and a Pogo game together. To facilitate this, Pogo provides a mixin
called HasWidgetsOverlay
which will enable any Flutter widget to be shown on top of your game instance. This makes it easy to create things like a pause menu or an inventory screen, for example.
To use it, simply add the HasWidgetsOverlay
mixin
on your game class, by doing so, you will have two new methods available addWidgetOverlay
and removeWidgetOverlay
, like the name suggests, they can be used to add, or remove widgets overlay above your game, they can be used as shown below:
addWidgetOverlay(
"PauseMenu", // Your overlay identifier
Center(child:
Container(
width: 100,
height: 100,
color: const Color(0xFFFF0000),
child: const Center(child: const Text("Paused")),
),
) // Your widget, this can be any Flutter widget
);
removeWidgetOverlay("PauseMenu"); // Use the overlay identifier to remove the overlay
Under the hood, Flame uses a Stack widget to display the overlay, so it is important to note that the order which the overlays are added matter, where the last added overlay will be in front of those added before.
See the widgets overlay example app.