Vertical lines between tiles when camera is moving - flutter

I'm trying to build a simple side-scroller game with a level built of square tiles using Flame.
#override
Future<void> onLoad() async {
final orange = Paint()..color = Color(0xFFFF9000);
final double tileSize = 64;
for (var i = 0; i <= 100; i++) {
add(RectangleComponent(position: Vector2(i * tileSize, 100), size: Vector2.all(tileSize), paint: orange));
}
}
When the screen is static, everything works as expected. However, when I add camera movement, I see vertical lines between the tiles.
#override
void update(double dt) {
camera.moveTo((Vector2(camera.position.x + 1, 0)));
super.update(dt);
}
I suspect it might be something to do with Flutter antialiasing bug. Does anybody know if there's a workaround? Thanks!

This is indeed that bug, we have it documented on a few of our issues too (like this one for example https://github.com/flame-engine/flame/issues/1888)
You can try to use Impeller if that is an option for you, where this bug shouldn't be present.
Other workarounds would be to draw the same color underneath the tiles where they are overlapping, that is of course not always possible though.
And the other option is to use a camera that only moves in full pixels, so that there are no rounding errors.

Related

How to make BodyDef smooth movement

I tried to use the method setTransform like this:
#override
void update(double dt) {
super.update(dt);
increaseTimer.update(dt);
if (side == 3) {
body.setTransform(Vector2(0, gameRef.increasedHeight), 0);
}
}
But the item looks like it is flashing from point A to point B, and the Items above this body are falling. I just want this body and the items above to move smoothly in a direction , how to achieve this? Thanks, I found some methods like using MouseJoint, but I guess it is too complicated for my topic?
=========UPDATE==========
Hi spydon, thanks for reply, I checked your answer, sry I didnt describe my question clearly.
The item I want to keep moving upward is like a wall/ground so it is a static body, therefore applyLinearImpulse/applyForce does not work right (since these both works only for dynamic body?).
Therefore I found setTransform, which works for static body,
increasedHeight++; //<= in update method
body.setTransform(Vector2(0, increasedHeight), 0);
works fine which make my ground move upward in 1 unit, but if the distance is larger than 1 unit, like
increasedHeight = increasedHeight + 10;,
the ground will be beamed to top and balls on this ground will be falling, which I don't want to, I tried to make balls and ground move together upward, is it possible?
Thanks for your time!
=========2.UPDATE==========
Hi Spydon, thanks again for your help! Plz check the example I created, since this Ground didn't move upward as I expected and just stuck in the position ...
class Ground extends SpriteBodyComponent {
Vector2 groundPosition;
bool removed = false;
final velocity = Vector2(0, 1000);
Ground({Sprite sprite, Vector2 size, this.groundPosition}) : super(sprite, size);
#override
Body createBody() {
final shape = CircleShape()..radius = size.x / 4;
var position = groundPosition.clone();
var worldPosition = viewport.getScreenToWorld(position);
final fixtureDef = FixtureDef()
..shape = shape
..restitution = 0.1
..density = 0.1
..friction = 0.1;
final bodyDef = BodyDef()
..userData = this
..angularDamping = 0.1
..position = worldPosition
..type = BodyType.STATIC;
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
#override
void update(double dt) {
super.update(dt);
body.setTransform(velocity * dt, 0);
print('body position == ${body.position.y}'); //<= body position == 16.667
}
}
You should almost never use setTransform on dynamic bodies, since this disturbs the physics calculations. If you are not certain that you need the physics simulation you most likely want to go with pure Flame and use one of the MoveEffects instead.
If you do need Forge2D, you should either use body.applyLinearImpulse or body.applyForce, depending on how you want to affect your bodies movement.
You can read more about it here and you can check out the flame_forge2d examples here, you can get to the code for each example by pressing < > in the upper right corner.
Reply to updated question:
You should change these things in your update method which gives you a delta time dt, this delta time you use together with the velocity that you want to the body to change with, for example:
final velocity = Vector2(0, 100); // Will move with 100px/s
#override
void update(double dt) {
if(!velocity.isZero) {
// Here you have to multiply with dt, to make the transform become px/s
body.setTransform(velocity * dt, 0);
}
}

Is there a max speed in Forge2D

When I try to do applyForce or applyLinearImpulse, I can only get a slow (but stable) speed regardless of how much force I add. Is there a max speed that is applied and restricting my bodies from going faster? I want to be able to have a bullet shooting effect.
I have checked some tutorial, but the velocity still seems too slow, even if I set body.linearVelocity = Vector2(5000, -5000); it moves slow.
#override
bool onTapDown(TapDownInfo info) {
body.applyLinearImpulse(Vector2(5, -1) * 1000000000);
return false;
}
gravity is zero, and here is body data:
#override
Body createBody() {
final Shape shape = CircleShape()..radius = 30;
final bodyDef = BodyDef(
userData: this,
angularDamping: 0,
position: Vector2(100, 500),
type: BodyType.dynamic,
);
final fixtureDef = FixtureDef(shape)
..shape = shape
..restitution = 1
..density = 0.0001
..friction = 0;
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
thank you!
This is due to that you have set the zoom level to 1, instead of 10 which is the default. This makes the bodies hit the top speed very quickly, so instead you should just make the bodies smaller and zoom in on them. This is not only Forge2D specific, but applies to pretty much all ports of box2d and box2d itself. You can read more about it here.

How to render DistanceJoint

I need to render a DistanceJoint, just a line connecting the 2 anchors, nothing fancy. I've seen something about a render method here but I coulen't figure out how to use it. I also don't mind using debug features. Thank you very much :)
Since you have tagged the question with Flame I'm guessing that you are using flame_forge2d?
The link that you provide is for pure forge2d web, but you should be able to do it in a similar fashion in flame_forge2d.
I would try something like this in your Forge2DGame:
final _bodyARenderPosition = Vector2.zero();
final _bodyBRenderPosition = Vector2.zero();
#override
void render(Canvas c) {
super.render(c);
c.save();
c.scale(camera.zoom);
for (final joint in world.joints) {
_bodyARenderPosition
..setFrom(joint.bodyA.position)
..y *= -1;
_bodyBRenderPosition
..setFrom(joint.bodyB.position)
..y *= -1;
c.drawLine(
_bodyARenderPosition.toOffset(),
_bodyBRenderPosition.toOffset(),
debugPaint,
);
}
c.restore();
}

Cropping an image in flutter

So I've been trying really hard to crop an image according to my needs in flutter.
Problem statement:
I have a screen and in that screen I show a frame while the device camera is run on the background. Now, what I want is that whenever the user clicks a photo, only the area of that image inside the frame should be kept and rest should be cropped.
What I have done so far?
Added a package image 3.1.3
Wrote code to fetch x,y coordinates of my frame.
Using the calculated x,y coordinates and copyCrop method from the Image package to crop the clicked image.
Now the problem is that I do not know how copyCrop works and the code right now does not give me the expected results.
final GlobalKey _key = GlobalKey();
void _getOffset(GlobalKey key) {
RenderBox? box = key.currentContext?.findRenderObject() as RenderBox?;
Offset? position = box?.localToGlobal(Offset.zero);
if (position != null) {
setState(() {
_x = position.dx;
_y = position.dy;
});
}
}
I assign this _key to my Image.file(srcToFrameImage) and the function above yields 10, 289.125
Here 10 is the offset from x and 289.125 is the offset from y. I used this tutorial for the same.
Code to crop my image using the Image package:
var bytes = await File(pictureFile!.path).readAsBytes();
img.Image src = img.decodeImage(bytes)!;
img.Image destImage = img.copyCrop(
src, _x!.toInt(), _y!.toInt(), src.width, src.height);
var jpg = img.encodeJpg(destImage);
await File(pictureFile!.path).writeAsBytes(jpg);
bloc.addFrontImage(File(pictureFile!.path));
Now, can anyone tell me how i can do this effectively? Right now, it does crop my image but not as I want it to be. It would be really great if someone could tell me how does copyCrop work and what is the meaning of all these different parameters that we pass into it.
Any help would be appreciated.
Edit:
Now, as you can see, i only want the image between this frame to be kept after being captured and rest to be cropped off.

Forge2DGame: No effect setting - body.position.setFrom(info.delta.game)

From this example you can drag around(not at the draggable point but some factor) a BodyComponent by setting body.applyLinearImpulse.
If I try to drag around, setting body.position I get no effect. I was hoping to be able to drag the BodyComponent around at the specific drag point.
Sample code line 37:
#override
bool onDragUpdate(DragUpdateInfo info) {
// final worldDelta = Vector2(1, -1)..multiply(info.delta.game);
// body.applyLinearImpulse(worldDelta * 1000);
body.position.setFrom(info.delta.game);
return false;
}
You should never manipulate body.position directly, since that could break the stability of the physics engine.
For your use-case you probably want to use a MouseJoint instead:
https://github.com/flame-engine/flame/blob/ba617790e4a7ca4dc03f4a2e29de43d42efd3482/packages/flame_forge2d/example/lib/mouse_joint_sample.dart