mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-02 03:15:43 +08:00
fix: The visibleGameSize should be based on viewport.virtualSize (#2945)
The `visibleGameSize` should be based on the virtual size of the viewport, otherwise it won't work for `FixedResolutionViewport` for example. We noticed this when using the `ScreenHitbox` in a world that was looked upon by a camera with a `FixedResolutionViewport`.
This commit is contained in:
@ -2,41 +2,41 @@ import 'package:flame/collisions.dart';
|
|||||||
import 'package:flame/components.dart';
|
import 'package:flame/components.dart';
|
||||||
import 'package:flame/events.dart';
|
import 'package:flame/events.dart';
|
||||||
import 'package:flame/game.dart';
|
import 'package:flame/game.dart';
|
||||||
import 'package:flame/input.dart';
|
|
||||||
import 'package:flutter/material.dart' hide Image, Draggable;
|
import 'package:flutter/material.dart' hide Image, Draggable;
|
||||||
|
|
||||||
class CirclesExample extends FlameGame with HasCollisionDetection, TapDetector {
|
class CirclesExample extends FlameGame {
|
||||||
static const description = '''
|
static const description = '''
|
||||||
This example will create a circle every time you tap on the screen. It will
|
This example will create a circle every time you tap on the screen. It will
|
||||||
have the initial velocity towards the center of the screen and if it touches
|
have the initial velocity towards the center of the screen and if it touches
|
||||||
another circle both of them will change color.
|
another circle both of them will change color.
|
||||||
''';
|
''';
|
||||||
|
|
||||||
@override
|
CirclesExample()
|
||||||
Future<void> onLoad() async {
|
: super(
|
||||||
add(ScreenHitbox());
|
camera: CameraComponent.withFixedResolution(width: 600, height: 400),
|
||||||
}
|
world: MyWorld(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyWorld extends World with TapCallbacks, HasCollisionDetection {
|
||||||
|
MyWorld() : super(children: [ScreenHitbox()..debugMode = true]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onTapDown(TapDownInfo info) {
|
void onTapDown(TapDownEvent info) {
|
||||||
add(MyCollidable(info.eventPosition.widget));
|
add(MyCollidable(position: info.localPosition));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyCollidable extends PositionComponent
|
class MyCollidable extends PositionComponent
|
||||||
with HasGameReference<CirclesExample>, CollisionCallbacks {
|
with HasGameReference<CirclesExample>, CollisionCallbacks {
|
||||||
|
MyCollidable({super.position})
|
||||||
|
: super(size: Vector2.all(30), anchor: Anchor.center);
|
||||||
|
|
||||||
late Vector2 velocity;
|
late Vector2 velocity;
|
||||||
final _collisionColor = Colors.amber;
|
final _collisionColor = Colors.amber;
|
||||||
final _defaultColor = Colors.cyan;
|
final _defaultColor = Colors.cyan;
|
||||||
late ShapeHitbox hitbox;
|
late ShapeHitbox hitbox;
|
||||||
|
|
||||||
MyCollidable(Vector2 position)
|
|
||||||
: super(
|
|
||||||
position: position,
|
|
||||||
size: Vector2.all(100),
|
|
||||||
anchor: Anchor.center,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onLoad() async {
|
Future<void> onLoad() async {
|
||||||
final defaultPaint = Paint()
|
final defaultPaint = Paint()
|
||||||
@ -46,8 +46,8 @@ class MyCollidable extends PositionComponent
|
|||||||
..paint = defaultPaint
|
..paint = defaultPaint
|
||||||
..renderShape = true;
|
..renderShape = true;
|
||||||
add(hitbox);
|
add(hitbox);
|
||||||
final center = game.size / 2;
|
velocity = -position
|
||||||
velocity = (center - position)..scaleTo(150);
|
..scaleTo(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -152,7 +152,7 @@ class Viewfinder extends Component
|
|||||||
Rect? visibleRect;
|
Rect? visibleRect;
|
||||||
@protected
|
@protected
|
||||||
Rect computeVisibleRect() {
|
Rect computeVisibleRect() {
|
||||||
final viewportSize = camera.viewport.size;
|
final viewportSize = camera.viewport.virtualSize;
|
||||||
final currentTransform = transform;
|
final currentTransform = transform;
|
||||||
currentTransform.globalToLocal(_zeroVector, output: _topLeft);
|
currentTransform.globalToLocal(_zeroVector, output: _topLeft);
|
||||||
currentTransform.globalToLocal(viewportSize, output: _bottomRight);
|
currentTransform.globalToLocal(viewportSize, output: _bottomRight);
|
||||||
|
|||||||
@ -115,5 +115,41 @@ void main() {
|
|||||||
expect(testBlock.endCounter, 0);
|
expect(testBlock.endCounter, 0);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
runCollisionTestRegistry({
|
||||||
|
'collides with FixedResolutionViewport': (hasCollisionDetection) async {
|
||||||
|
final game = hasCollisionDetection as FlameGame;
|
||||||
|
game.camera = CameraComponent.withFixedResolution(
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
);
|
||||||
|
final testBlock = TestBlock(
|
||||||
|
Vector2.all(-50),
|
||||||
|
Vector2.all(2),
|
||||||
|
)..anchor = Anchor.center;
|
||||||
|
final screenHitbox = ScreenHitbox();
|
||||||
|
await game.world.addAll([screenHitbox, testBlock]);
|
||||||
|
await game.ready();
|
||||||
|
game.update(0);
|
||||||
|
|
||||||
|
expect(testBlock.startCounter, 1);
|
||||||
|
expect(testBlock.onCollisionCounter, 1);
|
||||||
|
expect(testBlock.endCounter, 0);
|
||||||
|
|
||||||
|
testBlock.position = Vector2.all(50);
|
||||||
|
game.update(0);
|
||||||
|
|
||||||
|
expect(testBlock.startCounter, 1);
|
||||||
|
expect(testBlock.onCollisionCounter, 2);
|
||||||
|
expect(testBlock.endCounter, 0);
|
||||||
|
|
||||||
|
testBlock.position = Vector2.all(0);
|
||||||
|
game.update(0);
|
||||||
|
|
||||||
|
expect(testBlock.startCounter, 1);
|
||||||
|
expect(testBlock.onCollisionCounter, 2);
|
||||||
|
expect(testBlock.endCounter, 1);
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user