Learning increasing speed without lag using Dunk It
One of the most exciting parts of arcade game development is increasing speed over time. Players enjoy games that slowly become more intense because it creates pressure excitement and challenge. Dunk It is a perfect example of this idea. The ball starts moving slowly but after every successful round the movement speed increases and the gameplay becomes harder.
Many beginner developers make a simple mistake when creating speed based games. They increase movement speed incorrectly and the game starts lagging stuttering or behaving differently on different devices. Sometimes the movement becomes too fast on high refresh rate phones and too slow on older devices. This creates an unfair gameplay experience.
In this tutorial you will learn how to increase speed smoothly without causing lag. You will understand how game loops work how frame independent movement works and how to create scalable movement systems in Flutter Flame games.
The concepts you learn here are used in endless runners reaction games sports games shooting games and almost every arcade game. Once you understand smooth speed progression you can create games that feel professional and responsive.
Understanding why lag happens in games
Before learning smooth speed systems you need to understand what actually causes lag in games. Many people think lag only comes from graphics but that is not true. Lag can happen because of bad logic too.
One common mistake is updating movement using fixed values instead of time based calculations. For example many beginners write movement like this.
ballX += 5;
This looks simple but it creates problems. Faster devices run more frames every second which means the movement becomes faster. Slower devices run fewer frames which makes movement slower.
This creates inconsistent gameplay. A player using a gaming phone may experience a much faster ball compared to someone using a basic device.
The correct way is using delta time movement.
ballX += speed * dt;
Here dt means delta time. It represents the time difference between frames. This keeps movement smooth and equal across devices.
Creating the basic Dunk It game setup
Let us first create the basic game structure. Start by importing Flame and creating the game class.
import 'package:flame/game.dart';
import 'package:flutter/material.dart';
void main() {
runApp(
GameWidget(
game: DunkItGame(),
),
);
}
class DunkItGame extends FlameGame {
}
This creates the foundation of the game. Next we need variables for ball movement.
class DunkItGame extends FlameGame {
double ballX = 0;
double ballY = 120;
double ballSize = 50;
double speed = 250;
bool movingRight = true;
}
These variables control the basketball position size and movement speed.
Making the ball move smoothly
The update method is the heart of every Flame game. This method runs continuously every frame.
@override
void update(double dt) {
super.update(dt);
if (movingRight) {
ballX += speed * dt;
} else {
ballX -= speed * dt;
}
if (ballX <= 0) {
movingRight = true;
}
if (ballX + ballSize >= size.x) {
movingRight = false;
}
}
Here the basketball moves left and right continuously. The movement uses dt which keeps everything smooth.
Even if the phone frame rate changes the ball movement remains stable.
Rendering the basketball
Now let us draw the ball on screen.
@override
void render(Canvas canvas) {
super.render(canvas);
final ballPaint = Paint()
..color = Colors.orange;
canvas.drawCircle(
Offset(
ballX,
ballY,
),
ballSize,
ballPaint,
);
}
At this point you already have a smooth moving basketball.
Understanding safe speed increase systems
Increasing speed sounds easy but many developers increase speed incorrectly. Some people increase speed massively after every round.
speed += 500;
This creates unstable gameplay. Sudden speed jumps make movement impossible to control and can even cause visual skipping.
Instead you should slowly increase speed in small controlled steps.
speed += 20;
Small increases feel natural and fair to players.
Creating the tap system
Dunk It depends on player timing. The player taps the screen to drop the ball into hoops.
First enable tap detection.
import 'package:flame/input.dart';
class DunkItGame extends FlameGame
with TapDetector {
}
Now create the tap function.
@override
void onTapDown(TapDownInfo info) {
}
This method runs whenever the player touches the screen.
Increasing speed after successful shots
Now we can connect gameplay with difficulty progression. Every successful basket should slightly increase the speed.
int score = 0;
void scorePoint() {
score++;
speed += 15;
}
This creates progressive difficulty. The game slowly becomes more intense but still remains smooth.
Small increments are important because they prevent sudden movement spikes.
Adding a speed limit
One important optimization is setting a maximum speed. Without limits the game may eventually become impossible.
void scorePoint() {
score++;
if (speed < 700) {
speed += 15;
}
}
This prevents the basketball from reaching unrealistic speeds.
Good game design is not about making games impossible. It is about creating balanced challenge.
Why smooth movement matters
Smooth movement is extremely important in reaction based games like Dunk It. Players depend on visual timing. If the ball stutters or skips frames the player cannot react properly.
Smooth motion helps players predict movement patterns naturally. Human eyes track stable movement better than unstable movement.
This is why optimized speed systems are critical for arcade games.
Using delta time correctly
Delta time is one of the most important concepts in game development. It ensures equal gameplay across different devices.
Imagine two phones.
- One device runs at sixty frames every second
- Another device runs at one hundred twenty frames every second
If movement uses fixed values the faster device moves objects twice as fast. That creates unfair gameplay.
Delta time solves this by calculating movement using actual frame timing instead of assuming constant frame speed.
Bad movement example
ballX += 8;
This movement depends entirely on frame count which causes inconsistent gameplay.
Correct movement example
ballX += speed * dt;
This movement depends on real time instead of frame count.
Avoiding unnecessary rebuilds
Another common reason for lag in Flutter games is rebuilding widgets too often. Some beginners use normal Flutter widgets for everything inside the game loop.
Flame solves this problem because rendering happens directly on the canvas. This reduces unnecessary UI rebuilding.
Avoid using setState continuously for game movement because it can create performance issues in fast arcade games.
Using Flame for optimized rendering
Flame is designed specifically for games. It provides optimized rendering systems update loops and timing management.
This makes Flame much better for arcade gameplay compared to building everything manually with widgets.
Dunk It style games work perfectly with Flame because the engine handles continuous updates efficiently.
Adding difficulty progression naturally
Good difficulty progression feels natural. Players should not suddenly feel overwhelmed.
One good method is increasing speed gradually every few points instead of after every point.
void scorePoint() {
score++;
if (score % 3 == 0) {
speed += 20;
}
}
This creates smoother pacing.
Making movement predictable
Predictability is important in timing games. Players need enough consistency to improve through practice.
If movement changes randomly players feel frustrated because skill becomes less important.
Dunk It works well because the movement is smooth stable and predictable. The challenge comes from increasing speed not random unfair behavior.
Adding multiple hoops
The real Dunk It game contains multiple hoops. You can create hoop objects using simple position variables.
double hoopOneX = 100;
double hoopTwoX = 220;
double hoopThreeX = 340;
double hoopY = 500;
These hoop positions stay fixed while the basketball keeps moving faster.
Checking hoop collision
When the player taps the screen the game checks whether the ball is aligned with a hoop.
bool checkShot(double hoopX) {
double difference =
(ballX - hoopX).abs();
return difference < 35;
}
This creates a success zone around each hoop.
Why small success zones matter
Small success zones create challenge but the size must remain fair. If the target area is too small players become frustrated.
Professional games balance difficulty carefully. They reward skill while still feeling possible.
Optimizing game logic
Efficient game logic is important for smooth performance. Avoid creating unnecessary objects inside update loops.
Bad example.
@override
void update(double dt) {
Paint newPaint = Paint();
}
This creates new objects every frame which wastes memory.
Better approach.
final ballPaint = Paint()
..color = Colors.orange;
Create reusable objects outside the update loop whenever possible.
Adding score text efficiently
Displaying score is important but it should also remain optimized.
final scoreText = TextPaint(
style: const TextStyle(
color: Colors.white,
fontSize: 30,
fontWeight: FontWeight.bold,
),
);
Then render it inside the canvas.
scoreText.render(
canvas,
"Score $score",
Vector2(20, 20),
);
This approach is lightweight and efficient.
Understanding player psychology
Speed increase systems are not only technical features. They also affect player emotions.
Slow starts help beginners feel comfortable. Gradual speed increases create tension and excitement. Fast movement near higher scores creates pressure which makes success feel rewarding.
Good arcade games carefully control this emotional curve.
Testing on different devices
Always test your game on multiple devices if possible. Some phones have powerful processors while others are slower.
Delta time movement helps maintain fairness but testing is still important for real world performance.
Final thoughts
Learning how to increase speed smoothly without lag is one of the most valuable skills in game development. Almost every arcade game uses some type of progressive difficulty system.
In this tutorial you learned how to create smooth movement using delta time how to safely increase speed how to prevent lag and how to optimize gameplay systems for better performance.
Dunk It is a great learning project because it combines timing movement reaction and difficulty progression into one simple but powerful gameplay system.
Keep experimenting with different movement styles speed curves and difficulty systems. The more you practice these concepts the easier it becomes to create professional quality Flutter games using Flame.