1

Set Up a Flutter Project and Basic App Structure

Create a new Flutter project and open main.dart. Define a simple app structure with a main MyApp widget.

πŸ’‘ Tip: Use the button on the right side to easily copy the code.

import 'package:flutter/material.dart';

void main() {
    runApp(const MyApp());
}

class MyApp extends StatelessWidget {
    const MyApp({super.key});

    @override
    Widget build(BuildContext context) {
    return MaterialApp(
        title: 'BounceMaster 3D',
        theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        home: const BounceMasterGame(),
    );
    }
}
2

Create the Main Game Widget

Define a new BounceMasterGame widget and a corresponding BounceMasterGameState state. This widget will host the game.

πŸ’‘ Tip: Use the button on the right side to easily copy the code.

class BounceMasterGame extends StatefulWidget {
    const BounceMasterGame({super.key});
    
    @override
    BounceMasterGameState createState() => BounceMasterGameState();
    }
    
    class BounceMasterGameState extends State<BounceMasterGame> {
    @override
    Widget build(BuildContext context) {
        return Scaffold(
        appBar: AppBar(title: const Text('BounceMaster 3D')),
        body: Container(color: Colors.black87), // Game area background
        );
    }
    }
3

Define the Ball Class

Create a Ball class with properties for position, velocity, and constants for gravity and bounce. Include an update method to handle ball movement.

πŸ’‘ Tip: Use the button on the right side to easily copy the code.

class Ball {
    double x, y, z;
    double velocityX, velocityY, velocityZ;
    static const double gravity = 0.5;
    static const double bounce = 0.7;
    double bounceMultiplier = 1.0; // To increase bounce effect
    
    Ball()
        : x = 0.0,
            y = 0.0,
            z = 0.0,
            velocityX = 2.0,
            velocityY = 0.0,
            velocityZ = 1.0;
    
    void update() {
        x += velocityX;
        y += velocityY;
        z += velocityZ;
    
        velocityY -= gravity; // Apply gravity
    
        if (x.abs() > 150) {
        velocityX *= -bounce * bounceMultiplier;
        x = x.sign * 150;
        }
        if (y < -200) {
        velocityY *= -bounce * bounceMultiplier;
        y = -200;
        }
        if (z.abs() > 100) {
        velocityZ *= -bounce * bounceMultiplier;
        z = z.sign * 100;
        }
    }
    
    void increaseBounce() {
        bounceMultiplier += 0.2; // Method to increase bounce
    }
    }
    
4

Add Game Control Logic

Update BounceMasterGameState to start and end the game using a timer. Each tick of the timer updates the ball’s position and increments the score.

πŸ’‘ Tip: Use the button on the right side to easily copy the code.


class BounceMasterGameState extends State<BounceMasterGame> {
    Ball? ball;
    Timer? gameTimer;
    int score = 0;
    bool isGameRunning = false;
    
    void startGame() {
        if (!isGameRunning) {
        setState(() {
            ball = Ball();
            score = 0;
            isGameRunning = true;
        });
    
        gameTimer = Timer.periodic(const Duration(milliseconds: 16), (timer) {
            setState(() {
            ball!.update();
            score += 1;
            });
        });
        }
    }
    
    void endGame() {
        gameTimer?.cancel();
        setState(() {
        isGameRunning = false;
        ball = null;
        });
    }
    
    void increaseBounce() {
        setState(() {
        ball?.increaseBounce();
        });
    }
    
    @override
    void dispose() {
        gameTimer?.cancel();
        super.dispose();
    }
    }
                              
5

Add UI Controls

Add "Start Game", "End Game", and "Bounce" buttons in the BounceMasterGameState widget to control game actions.

πŸ’‘ Tip: Use the button on the right side to easily copy the code.

@override
Widget build(BuildContext context) {
    return Scaffold(
    appBar: AppBar(
        title: const Text('BounceMaster 3D'),
        actions: [
        Center(
            child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text(
                'Score: $score',
                style: const TextStyle(fontSize: 20),
            ),
            ),
        ),
        ],
    ),
    body: Stack(
        children: [
        Container(color: Colors.black87), // Game area
        Positioned(
            bottom: 20,
            left: 0,
            right: 0,
            child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
                ElevatedButton(onPressed: isGameRunning ? null : startGame, child: const Text('Start Game')),
                ElevatedButton(onPressed: isGameRunning ? endGame : null, child: const Text('End Game')),
                ElevatedButton(onPressed: isGameRunning ? increaseBounce : null, child: const Text('Bounce')),
            ],
            ),
        ),
        ],
    ),
    );
}
6

Draw the Ball and Background

Create a GamePainter class to render the ball and grid. Update BounceMasterGameState to use this painter.

πŸ’‘ Tip: Use the button on the right side to easily copy the code.

class GamePainter extends CustomPainter {
    final Ball? ball;
    
    GamePainter(this.ball);
    
    @override
    void paint(Canvas canvas, Size size) {
        final paint = Paint()..color = Colors.white;
        drawGrid(canvas, size);
    
        if (ball != null) {
        double perspective = (ball!.z + 200) / 300;
        double ballSize = 20 * perspective;
    
        paint.color = Colors.black54; // Shadow
        canvas.drawCircle(Offset(size.width / 2 + ball!.x, size.height / 2 - 200), ballSize * 0.8, paint);
    
        paint.color = Colors.blue; // Ball
        canvas.drawCircle(Offset(size.width / 2 + ball!.x, size.height / 2 - ball!.y), ballSize, paint);
        }
    }
    
    void drawGrid(Canvas canvas, Size size) {
        final paint = Paint()..color = Colors.grey.withOpacity(0.3);
        for (double x = -200; x <= 200; x += 40) {
        canvas.drawLine(Offset(size.width / 2 + x, 0), Offset(size.width / 2 + x, size.height), paint);
        }
        for (double y = 0; y <= size.height; y += 40) {
        canvas.drawLine(Offset(size.width / 2 - 200, y), Offset(size.width / 2 + 200, y), paint);
        }
    }
    
    @override
    bool shouldRepaint(GamePainter oldDelegate) => true;
    }
                              
7

Update Game UI to Render the Ball

Add the GamePainter to the build method of BounceMasterGameState to display the ball.

πŸ’‘ Tip: Use the button on the right side to easily copy the code.

body: Stack(
children: [
    Container(
    color: Colors.black87,
    child: CustomPaint(
        painter: GamePainter(ball),
        size: Size.infinite,
    ),
    ),
    // Other UI controls as defined earlier
],
),

8

Run the App and Test

Now, run the app. You should be able to see the ball moving and bouncing within the screen, and clicking the "Bounce" button will make the ball bounce with more intensity each time.

πŸ’‘ Tip: Use the button on the right side to easily copy the code.


//  Now, run the app. 
 
Step 1 of 8