revoluteJointDef.localAnchorA y-axes looks wrong - flame

From this, I would expect the following RevoluteJoint bodyB, to be higher up than the blue box on the y-axe - setting
revoluteJointDef.localAnchorA?
flame_forge2d: ^0.11.0
class Box extends BaseBox { // just a BodyComponent for same shape
BaseBox? boxB;
Box(position, paint, [this.boxB]) : super(position, paint);
#override
Body createBody() {
super.createBody();
if (this.boxB != null) {
paint.color = Colors.blue;
final revoluteJointDef = RevoluteJointDef();
revoluteJointDef.bodyA = body;
revoluteJointDef.bodyB = this.boxB!.body;
revoluteJointDef.localAnchorA.setFrom(Vector2(1, 1));
RevoluteJoint joint = RevoluteJoint(revoluteJointDef);
world.createJoint(joint);
}
return body;
}
}
I would expect it to be like this:

In flame_forge2d 0.11.0 the coordinate system was flipped on the y-axis to be the same coordinate system as Flame, so larger y-values will result in further down, instead of further up like it is in normal forge2d.
Just negate the y-value of the anchor and you should get your intended result:
revoluteJointDef.localAnchorA.setFrom(Vector2(1, -1));

Related

Flutter canvas not rendering as expected

I am trying to render a grid with flutter canvas with Canvas.drawLine method.
Some lines are rendered semi-transparent and some are not even being rendered on the canvas.
class Background extends PositionComponent with HasGameRef<RokokoGame>{
Offset start = Offset.zero;
Offset end = Offset.zero;
// will be different across devices
late final double canvasX;
late final double canvasY;
final int cellSize = GameConfig.cellSize;
Background(this.canvasX, this.canvasY);
#override
Future<void>? onLoad() {
start = Offset(0, 0);
end = Offset(this.canvasX, this.canvasY);
}
#override
void render(Canvas canvas) {
canvas.drawRect(Rect.fromPoints(Offset.zero, end), Styles.white);
_drawVerticalLines(canvas);
_drawHorizontalLines(canvas);
}
void _drawVerticalLines(Canvas c) {
for (double x = start.dx; x <= end.dx; x += cellSize) {
c.drawLine(Offset(x, start.dy), Offset(x, end.dy), Styles.red);
}
}
void _drawHorizontalLines(Canvas c) {
for (double y = start.dy; y <= end.dy; y += cellSize) {
c.drawLine(Offset(start.dx, y), Offset(end.dx, y), Styles.blue);
}
}
}
So, i was able to solve the issue by applying some stroke width in my Styles class.
class Styles {
static Paint white = BasicPalette.white.paint();
static Paint blue = BasicPalette.blue.paint()..strokeWidth = 3;
static Paint red = BasicPalette.red.paint()..strokeWidth = 3;
}

Make fixture(shape) transparent when drawing walls

From createBoundaries used in examples, I see how to create "Walls"/EdgeShape.
When moving the camera I get lines drawn. Du you know how to not draw these lines or make them transparent - looked in the FixtureDef?
import 'package:flame_forge2d/flame_forge2d.dart';
class Wall extends BodyComponent {
final Vector2 start;
final Vector2 end;
Wall(this.start, this.end);
#override
Body createBody() {
final shape = EdgeShape()..set(start, end);
final fixtureDef = FixtureDef(shape)
..restitution = 0.0
..friction = 0.3;
final bodyDef = BodyDef()
..userData = this // To be able to determine object in collision
..position = Vector2.zero()
..type = BodyType.static;
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
}
Set renderBody = false or override render to be empty in the BodyComponent, Wall in this case.

How to get transformed widget real position on screen

Let's say I have a container with a transform applied to it. Because of the transform it's drawn to a slightly shifted position on screen (while its layout position remain the original one, without the transform).
Eg:
Here I have two containers in a stack. Blue one is without transform. And red one is with transform.
https://dartpad.dev/?id=5fc0a808ea606a97216bb06df0824b77&null_safety=true
How do I determine actual position of red one on screen? Since transform is applied at the paint time (not layout time), the usual ways of getting renderobject and using it to obtain position relative to ancestor doesn't work. It just gives same rect for both.
Blue Rect Rect.fromLTRB(0.0, 0.0, 400.0, 400.0)
Red Rect Rect.fromLTRB(0.0, 0.0, 400.0, 400.0)
Is there any way to get the actual position of red/transformed widget relative to ancestor/screen?
Finally found a way. You just need to find a child renderobject which is actually positioning things.
// function to get relative rect from ancestor
Rect getRenderBoxRect(RenderBox rb, RenderObject ancestor) {
final size = rb.size;
final topLeft = rb.localToGlobal(Offset.zero, ancestor: ancestor);
final bottomRight =
rb.localToGlobal(Offset(size.width, size.height), ancestor: ancestor);
return Rect.fromPoints(topLeft, bottomRight);
}
// function to get specific type of child renderobject
RenderObject? findRenderObjectByType(RenderObject parent, Type type) {
RenderObject? found;
parent.visitChildren((child) {
if (found != null) {
return;
}
if (child.runtimeType == type) {
found = child;
return;
}
found ??= findRenderObjectByType(child, type);
});
return found;
}
// then calculate rect in post frame callback using global key
Widget build(BuildContext context) {
WidgetsBinding.instance?.addPostFrameCallback((duration) {
final ancestor = stackKey.currentContext!.findRenderObject()!;
final redRo = redKey.currentContext!.findRenderObject()!;
final redRoT = findRenderObjectByType(redRo, RenderPositionedBox);
if (redRoT != null) {
print("RECT ${getRenderBoxRect(redRoT as RenderBox, ancestor)}");
}
}
}
Prints:
RECT Rect.fromLTRB(200.0, 0.0, 683.0, 500.0)
This gives you the rect for real position (black border in the following image):

Flutter, How to remove pan following effect from interactiveviewer

From Here: https://api.flutter.dev/flutter/widgets/GestureDetector/onPanEnd.html
there is velocity concept.
I want to remove after drag by some velocity.
How to remove following moving or make velocity to 0?
I want to very not flexible interactive viewer.
EDIT:
STICKY TRANSFORMCONTROLLER CODE:
class CustomSecondTransformationController extends TransformationController {
CustomSecondTransformationController([Matrix4? value])
: super(value ?? Matrix4.identity());
set before(Offset value) {
_before = value;
}
Offset toScene(Offset viewportPoint) {
Offset vp = viewportPoint;
final Matrix4 inverseMatrix = Matrix4.inverted(value);
final Vector3 untransformed = inverseMatrix.transform3(Vector3(
vp.dx,
vp.dy,
0,
));
return Offset(untransformed.x / 3, untransformed.y / 3);
}

how can I apply gravity to my gameobject in flutters flame library

I am having trouble applying gravity to a Rect object I want to fall freely along the Y-axis by updating Rect's position In my code with the body.position.y. Here is a snippet of my code :
import 'dart:ui';
import 'package:box2d_flame/box2d.dart';
import 'package:flame/sprite.dart';
import 'package:mimo/mimo-game.dart';
class Mimo {
final MimoGame game;
CircleShape shape;
Body body;
List<Sprite> mimoSprite;
List<Sprite> deadSprite;
double flyingSpriteIndex = 0;
Rect mimoRect;
bool isDead = false;
bool isOffScreen = false;
Mimo(this.game, double x, double y) {
shape = CircleShape(); //build in shape, just set the radius
shape.p.setFrom(Vector2.zero());
shape.radius = .1; //10cm ball
BodyDef bd = BodyDef();
bd.position = new Vector2(x,y);
bd.type = BodyType.DYNAMIC;
body = game.world.createBody(bd);
body.userData = this;
FixtureDef fd = FixtureDef();
fd.restitution = 0.5;
fd.density = 0.05;
fd.friction = 0;
fd.shape = shape;
body.createFixtureFromFixtureDef(fd);
mimoSprite = List();
mimoSprite.add(Sprite('mimo/mimo-1.png'));
mimoSprite.add(Sprite('mimo/mimo-2.png'));
mimoSprite.add(Sprite('mimo/mimo-3.png'));
mimoSprite.add(Sprite('mimo/mimo-4.png'));
mimoSprite.add(Sprite('mimo/mimo-5.png'));
deadSprite = List();
mimoRect = Rect.fromLTWH(body.position.x, body.position.y, game.mimoSize, game.mimoSize);
}
void render(Canvas c) {
mimoSprite[flyingSpriteIndex.toInt()].renderRect(c, mimoRect.inflate(2));
}
void update(double t) {
mimoRect = mimoRect.translate(body.position.x, body.position.y);
}
}
in the update method I use the line mimoRect = mimoRect.translate(body.position.x, body.position.y); so the body.position can update my Rect object in real-time. but nothing happens as my spawned object is always fixed at a position and does not move. I decided to log body.position.y to the console and noticed it does not change.
In my main class, I create a world object like this :
//Needed for Box2D
static const int WORLD_POOL_SIZE = 100;
static const int WORLD_POOL_CONTAINER_SIZE = 10;
//Main physic object -> our game world
World world;
//Zero vector -> no gravity
final Vector2 _gravity = Vector2(0, 4.0);
Body body;
CircleShape shape;
//Scale to get from rad/s to something in the game, I like the number 5
double sensorScale = 5;
//Draw class
Paint paint;
//Initial acceleration -> no movement as its (0,0)
Vector2 acceleration = Vector2.zero();
MimoGame() {
world = new World.withPool(_gravity,
DefaultWorldPool(WORLD_POOL_SIZE, WORLD_POOL_CONTAINER_SIZE));
initialize();
}
Please any idea on what I can do?
You need to use the Box2DGame (flame 0.22.0^) class in flame for your game and the object that you want to apply gravity to needs to extend BodyComponent, then you create an instance of your BodyComponent in your Box2DGame and use the add function to add it to the game loop which will make sure that update and render is called on it every iteration.
There is a good example in the flame source here.
Also remember that if your gravity is positive, your object will be flying upwards.