fluttergame-physicsflameforge2d

How to use flame camera to zoom into an object without changing its dimensions?


I'm using flame and forge2d to create a simple app. I'm having trouble because the physics bodies I render in the game are too big so things falling etc. reach terminal velocity too quickly and everything seems very slow. To solve this, I would like to make everything a lot smaller but use the camera to zoom in so that my screen looks the same. However, I'm really having trouble implementing the camera and to be honest I don't quite understand it - I've read through the documentation, watched youtube tutorials, tried to add camera viewport etc. but I think I've been doing it incorrectly.

The code below simply displays a small red square in the middle of the screen (no forge2d stuff in there yet). How would I use flame's camera to zoom into the square so that is appears bigger without actually changing its dimensions? Really appreciate any help.

import 'package:flame/game.dart';
import 'package:flutter/material.dart';
import 'package:flame/components.dart';

void main() {
  runApp(
    GameWidget(
      game: SimpleGame(),
    ),
  );
}

class SimpleGame extends FlameGame {
  late RectangleComponent jarRectangle;

  // Declare these variables to store the rectangle dimensions
  double rectangleWidth = 50.0;
  double rectangleHeight = 50.0;

  @override
  Future<void> onLoad() async {
    super.onLoad();

    // Create a RectangleComponent for the jar (red color)
    jarRectangle = RectangleComponent()
      ..size = Vector2(rectangleWidth, rectangleHeight)  // Set size of the rectangle
      ..position = Vector2(200 - rectangleWidth / 2, 400 - rectangleHeight / 2); // Center it on the screen

    // Set the color using the paint property
    jarRectangle.paint = Paint()..color = Colors.red;

    // Add the rectangle to the game
    add(jarRectangle);
  }

  @override
  void update(double dt) {
    super.update(dt);
  }

  @override
  void render(Canvas canvas) {
    super.render(canvas);
  }
}

Solution

  • Ok so I figured it out! It wasn't super difficult - turns out I wasn't creating the world component for the camera correctly. The below code now has the same red rectangle (although dimensions might be slightly different). I've added a camera and centred its viewpoint to be the centre of the screen. You can now adjust the size of the camera to zoom in and out without changing the actual dimensions of the rectangle. I hope this is helpful!

    import 'package:flame/game.dart';
    import 'package:flutter/material.dart';
    import 'package:flame/components.dart';
    
    void main() {
      runApp(
        GameWidget(
          game: SimpleGame(),
        ),
      );
    }
    
    class SimpleGame extends FlameGame {
      late RectangleComponent jarRectangle;
      late World myWorld;
    
      @override
      Future<void> onLoad() async {
        super.onLoad();
    
        // Print the initial screen size when the game loads
        print('Screen size: $size');
    
        // Create the world component
        myWorld = World();
        await add(myWorld);
    
        // Calculate the center of the screen dynamically
        final screenCenter = size / 2;
    
        // Create a red rectangle component and add it to the world, centered on the screen
        jarRectangle = RectangleComponent(
          size: Vector2(100, 200),  // Width and height of the rectangle
          position: screenCenter - Vector2(50, 100),  // Centering the rectangle
          paint: Paint()..color = Colors.red,  // Set color to red
        );
        myWorld.add(jarRectangle);
    
        // Print the initial position of the rectangle
        print('Rectangle position: ${jarRectangle.position}');
    
        // Set up the camera to focus on the screen center
        final cameraComponent = CameraComponent.withFixedResolution(
          world: myWorld,  // Assign the world to the camera
          width: 500,
          height: 1000,
        );
    
        // Center the camera on the screen's center position
        cameraComponent.viewfinder.position = screenCenter;
    
        add(cameraComponent);
      }
    
      @override
      void update(double dt) {
        super.update(dt);
      }
    }