Advanced physics simulations in Flutter

Today we'll be learning how Flutter provides its users with a thrilling experience in being able to apply concepts of physics to their animations. Before we dive right in, let's have a brief recap of what Flutter offers.

Flutter

Flutter is a UI development toolkit primarily used for building applications for various platforms using a single codebase. It is completely open-source and is a product of Google.

Simply put, this means that developers can write the code once and use it on different platforms without having to start from scratch for each one.

Flutter in a few words
Flutter in a few words

Note: We offer various courses if you aim to continue your journey in learning Flutter!

Beginning Flutter: Android Mobile App Development

Learn Dart: First Step to Flutter

Dart

Flutter needs a programming language to build and run applications. Dart is used as the primary language for developing applications with the Flutter framework. We will be using Dart in our code as well.

How Flutter works
How Flutter works

Note: Before proceeding with the answer, ensure that your Flutter setup is complete.

Physics simulation

A physics simulation is a computer-based model that replicates the behavior of physical systems in a virtual environment. It basically tries to copy how real-world things move and interact with each other based on the rules of physics. Therefore, this helps us see how objects would behave in different situations without having to do actual physical experiments.

Flutter's physics module

Flutter offers a physics library that contains different simulations that work differently based on physics concepts. For instance, gravity simulation works by implementing a gravity environment to aid falls, while a spring simulation focuses on the stiffness of the spring or the mass of the object.

Flutter's physics library
Flutter's physics library

Basic physics simulations in Flutter

If you aim to get ahold of the basics first, feel free to check out our answer on basic physics simulations in Flutter.

Spring physics simulation walkthrough

In this Flutter code, we will create an exciting physics animation with bouncing balls. Our animation demonstrates the behavior of five balls, each with its own set of physics properties, bouncing in response to the physics simulation.

initState method

In the initState method, we initialize the animation controllers and the corresponding spring simulationthe variable seems as if its held by a real spring and therefore moves up and down settings for each ball. We change the values of stiffness, damping, and color for each ball. We use the addListener method of the animation controllers to build our UI again whenever the animation value changes. We then use controller.animateWith to trigger the physics-based animation for each ball. The animation will cause the balls to move based on our defined properties, resulting in a bouncing motion.

@override
void initState() {
super.initState();
ball1Data = BallData(stiffness: 100, damping: 1, color: Colors.blue);
ball2Data = BallData(stiffness: 200, damping: 1.2, color: Colors.red);
ball3Data = BallData(stiffness: 300, damping: 1.4, color: Colors.green);
ball4Data = BallData(stiffness: 400, damping: 1.6, color: Colors.yellow);
ball5Data = BallData(stiffness: 500, damping: 1.8, color: Colors.orange);
for (var ballData in [ball1Data, ball2Data, ball3Data, ball4Data, ball5Data]) {
ballData.controller = AnimationController(vsync: this, upperBound: 500)
..addListener(() {
setState(() {});
});
ballData.controller.animateWith(ballData.simulation);
}
}

The user interface

The user interface consists of a Column widget that includes an app bar and the main body. We divide our body into two sections. The first one contains a Text widget titled "Bouncing Balls," displayed in a white and bolded font using properties like fontWeight, color, and fontSize. The second section is a Container with a dark background color, simulating the floor where the balls bounce. Inside this container, we have a Stack widget to help position the balls.

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: Text(
'Cool Physics Animation',
style: TextStyle(fontSize: 24),
),
centerTitle: true,
backgroundColor: Colors.blueGrey[900],
elevation: 0,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 20.0),
child: Text(
'Bouncing Balls',
style: TextStyle(
fontSize: 32,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
Container(
width: double.infinity,
height: 300,
color: Colors.blueGrey[900],
child: Stack(
children: [
Positioned(
left: 50,
top: ball1Data.controller.value,
child: BallWidget(color: ball1Data.color),
),
Positioned(
left: 120,
top: ball2Data.controller.value * 1.5,
child: BallWidget(color: ball2Data.color),
),
Positioned(
left: 190,
top: ball3Data.controller.value * 0.8,
child: BallWidget(color: ball3Data.color),
),
Positioned(
left: 260,
top: ball4Data.controller.value * 1.2,
child: BallWidget(color: ball4Data.color),
),
Positioned(
left: 330,
top: ball5Data.controller.value * 0.5,
child: BallWidget(color: ball5Data.color),
),
],
),
),
],
),
),
);
}

BallWidget custom widget

We create a custom widget called BallWidget to represent the balls. The widget takes the color argument determining the ball's appearance. It's displayed as a circular container with our given color.

class BallWidget extends StatelessWidget {
final Color color;
BallWidget({this.color});
@override
Widget build(BuildContext context) {
return Container(
width: 50,
height: 50,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: color,
),
);
}
}

Note: Stateless widgets remain the same throughout while stateful widgets are subject to change due to interactivity.

AnimationController

The animation controllers and spring simulations work together to create the physics-based bouncing animation for each ball. The AnimationController updates the animation values, and the setState method rebuilds UI to show the moving balls.

Basically, the physics simulation is based on the spring equation, which in turn moves the balls.

  • 0.0 is the starting

  • 300.0 is the ending

  • 10 is the velocity

class BallData {
AnimationController controller;
final SpringSimulation simulation;
final double stiffness;
final double damping;
final Color color;
BallData({this.stiffness, this.damping, this.color})
: simulation = SpringSimulation(
SpringDescription(
mass: 1,
stiffness: stiffness,
damping: damping,
),
0.0,
300.0,
10,
);
}

Note: You can change the settings of the physics simulation to see how the effect on the shapes changes.

Complete code

Hurray! Our explanation is now complete, and we're ready to put together our code. The given code is completely executable, and you can experiment with it to see how these simulations work.

const express = require('express');
const cors = require('cors');
const path = require('path');

const app = express();
const port = 8080;

// Enable CORS for all routes
app.use(cors());

// Serve the Flutter web application
app.use(express.static(path.join(__dirname, 'build/web')));

// Start the server
app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

Starting screen

This is how our application starts initially.

The balls initially
The balls initially

Demonstration of physics simulation

Our animation is ready! Let's see how the balls move due to the spring simulation.

Physics simulation using gravity

Similar to the previous concept, we can make use of the GravitySimulation module to create a Flutter application with the force of gravity. The values can be changed according to our needs.

Here's how it works.

const express = require('express');
const cors = require('cors');
const path = require('path');

const app = express();
const port = 8080;

// Enable CORS for all routes
app.use(cors());

// Serve the Flutter web application
app.use(express.static(path.join(__dirname, 'build/web')));

// Start the server
app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});
  • We implement a gravity simulation to create a falling animation for multiple squares. The GravitySimulation class is used to model this.

  • We initialize three AnimationController instances to drive the animations and three GravitySimulation instances with different acceleration values for our squares.

  • The square positions are updated using the controller.value and the GravitySimulation.x(controller.value) methods within a Positioned widget. This causes the squares to fall with gravity-based animations on the screen.

Starting screen

This is how our application starts initially.

The squares initially
The squares initially

Demonstration of physics simulation

Our animation is ready! Let's see how different gravity values work on each square.

Use cases of physics simulations

Physics simulations in computer science can have amazing advantages, including but not limited to the list mentioned below.

Use cases

Realistic object movement in games and simulations

Natural-looking cloth and hair animations in animations and movies

Accurate physics-based collisions for game development

Dynamic fluid and particle effects in visual effects and simulations

Understanding complex physical phenomena in scientific research

Precise engineering simulations for structural analysis

Test your knowledge on Flutter’s physics simulation!

Question

How does the SpringSimulation differ from the GravitySimulation?

Show Answer

Free Resources

Copyright ©2024 Educative, Inc. All rights reserved