Flutter, How to remove pan following effect from interactiveviewer - flutter

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);
}

Related

revoluteJointDef.localAnchorA y-axes looks wrong

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));

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 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.

Snapping Behavior Custom ScrollPhysics

After some tinkering and Googling all over the place I became super frustrated with the API / lack of documentation for ScrollPhysics.
On Android you can use what's called a SnapHelper inside your RecyclerView (analogous to a ListView in Flutter) that will automatically snap to a certain position.
The SnapHelper does this on a position based API.
You can ask which View is currently in your chosen ViewPort and get its position and ask the RecyclerView to animate to that position.
Flutter on the other hand wants us to work with logical pixels, which makes this super trivial, common pattern difficult to implement.
All the solutions I found was to use items inside the list that have a fixed width/height and don't account for flinging gestures.
tl;dr How to implement this ๐Ÿ‘†in Flutter so it works for any item in a ListView?
I'm including the poor mans version we are currently using.
Which works, but not like we are used to on Android.
Especially passing the itemWidth is an eyesore
class SnappingListScrollPhysics extends ScrollPhysics {
final double itemWidth;
const SnappingListScrollPhysics({
#required this.itemWidth,
ScrollPhysics parent,
}) : super(parent: parent);
#override
SnappingListScrollPhysics applyTo(ScrollPhysics ancestor) => SnappingListScrollPhysics(
parent: buildParent(ancestor),
itemWidth: itemWidth,
);
double _getItem(ScrollPosition position) => (position.pixels) / itemWidth;
double _getPixels(ScrollPosition position, double item) => min(item * itemWidth, position.maxScrollExtent);
double _getTargetPixels(ScrollPosition position, Tolerance tolerance, double velocity) {
double item = _getItem(position);
if (velocity < -tolerance.velocity) {
item -= 0.5;
} else if (velocity > tolerance.velocity) {
item += 0.5;
}
return _getPixels(position, item.roundToDouble());
}
#override
Simulation createBallisticSimulation(ScrollMetrics position, double velocity) {
// If we're out of range and not headed back in range, defer to the parent
// ballistics, which should put us back in range at a page boundary.
if ((velocity <= 0.0 && position.pixels <= position.minScrollExtent) ||
(velocity >= 0.0 && position.pixels >= position.maxScrollExtent)) {
return super.createBallisticSimulation(position, velocity);
}
final Tolerance tolerance = this.tolerance;
final double target = _getTargetPixels(position, tolerance, velocity);
if (target != position.pixels) {
return ScrollSpringSimulation(spring, position.pixels, target, velocity, tolerance: tolerance);
}
return null;
}
#override
bool get allowImplicitScrolling => false;
}

Moving a body from one position to another on button press

I have a problem where the player releases a power attack,this powerattack must move upto a certain position and then get detached,how can i achieve this? I tried using setvelocity but it didnt work that well...pls help!!
Ok here's my attack method which is called when the button is pressed:
public void powerattack() {
float startBulletX = player.getX() + 30; //Get X position of character body
float startBulletY = player.getY(); //Get Y position of character body
final Sprite bullet = new Sprite(startBulletX, startBulletY,
resourcesManager.special_attack, vbom); //The special attack sprite
final FixtureDef bulletFixtureDef1 = PhysicsFactory.createFixtureDef(0,
0, 0, false, CATEGORYBIT_KNIFE, MASKBIT_KNIFE, (short) 0);
this.mBulletBody = PhysicsFactory.createBoxBody(physicsWorld, bullet,
BodyType.DynamicBody, bulletFixtureDef1);
mBulletBody.setLinearVelocity(20f,0);
this.physicsWorld.registerPhysicsConnector(new PhysicsConnector(bullet,
this.mBulletBody, true, false));
this.attachChild(bullet);
}
When i run this code the special attack body moves out of screen...I want to limit the power attack to a certain position i.e few distance away from the character.
I got the solution,I used onUpdate method and within that onupdate method i set the code as invisible,here's my code :)
public void powerattack() {
float startBulletX = player.getX() + 30;
float startBulletY = player.getY();
final Sprite ray = new Sprite(startBulletX, startBulletY,
resourcesManager.special_attack, vbom);
final Vector2 velocity = Vector2Pool.obtain(20f, 0);
final FixtureDef rayFixtureDef1 = PhysicsFactory.createFixtureDef(0, 0,
0, false, CATEGORYBIT_RAY, MASKBIT_RAY, (short) 0);
this.mRayBody = PhysicsFactory.createBoxBody(physicsWorld, ray,
BodyType.DynamicBody, rayFixtureDef1);
this.mRayBody.setLinearVelocity(velocity);
Vector2Pool.recycle(velocity);
this.physicsWorld.registerPhysicsConnector(new PhysicsConnector(ray,
this.mRayBody, true, false) {
/*Update method keeps checking whether the power attack reached the specific distance*/
#Override
public void onUpdate(float pSecondsElapsed) {
if (ray.getX() >= (player.getX() + 300)) {
ray.setVisible(false);
ray.setIgnoreUpdate(false);
}
super.onUpdate(pSecondsElapsed);
camera.onUpdate(0.1f);
}
});
mRayBody.setUserData("power");
this.attachChild(ray);
}