How to render DistanceJoint - flutter

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

Related

Vertical lines between tiles when camera is moving

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.

Vector2 bouncing off ScreenHitbox and other CircleHitbox

This question could be asked to any math wizard, but I am playing around in flame( loads of fun ), so I allow myself to ask it here.
My math is rusty but I have tried using reflect and normalized, but I am way off here. Can you help, and maybe give a direction for both ScreenHitbox & CircleHitbox?
I have CircleHitbox and a collision:
#override
void onCollisionStart(
Set<Vector2> intersectionPoints,
PositionComponent other,
) {
super.onCollisionStart(intersectionPoints, other);
if (other is ScreenHitbox) {
// velocity.reflect(other.position.normalized());
// velocity.reflect(other.size.normalized());
velocity.reflect(intersectionPoints.first.normalized());
// return;
}
}
Update: looking for normal on the collision?

Efficient Canvas rendering in Flutter

I have been trying to develop a drawing app and all the example codes including the one's from The Boring Flutter Development Show don't translate well into real-world usage.
The main problem being that CustomPaint's paint operation is too expensive and re-draws every point, every frame. And as the points increase the flutter app's render time per frame increases significantly
From the time I spent finding a solution to this problem, I found these
RepaintBoundary : Rasterizes layers
Custom Widget using SingleChildRenderObjectWidget and RenderProxyBox : must implement a paint method and no way of passing a controller
I don't think any of the above solutions work well for my needs: smooth canvas drawing operations without re-paint. I even tried simplifying the points and that didn't work either because of the inherent mechanism of CustomPaint
If there was a way to pass a canvas as a widget and attaching a controller it'll be easy to store the captured points and use basic canvas operations like canvas.drawPath() or canvas.drawLine() much efficiently
Any suggestion would be helpful. Thank you!
This is the Controller class
class DrawingController extends ChangeNotifier {
List<Offset> _points = []
.... // Perform operations on data points
....
void add(Offset point) {
_points.add(point);
notifyListeners();
}
}
This is the CustomPaint class
class Painter extends CustomPainter {
DrawingController controller;
Painter(this.controller) : super(repaint: controller); //This is important
#override
void paint(Canvas canvas, Size size) {
//Paint function
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
And in the Gesture detector simply call controller.add(point) to add new points as you grab them
I am not sure this is the most efficient way to paint but it reduced the paint times down to 13ms on a 60hz screen and 9ms on a 120Hz screen. One noticeable drawback is that a single stroke (onTapdownEvent to an onDragEndEvent) renders quite slowly(up to 18ms) when the stroke has many points. This problem disappears as soon as you start a new stroke. I tried asking on several forums and this is the best I could come up with after digging through the flutter source code.
I profiled this functionality on a snapdragon 855 device so the processor is not a bottleneck. If anyone finds a better solution please post it.
A helpful tip is to add a Timer.run(setState()). This way it only updates when it can. Instead of loading update1 update2 update3...etc. It loads update1 then if it can it loads update2 but if update1 took to long it goes to update3. In general it just looks smoother but doesn't necessarily speed it up. Sample:
scaleStart(ScaleStartDetails d) => startPoint = d.focalPoint - _offset;
scaleUpdate(ScaleUpdateDetails d) {
_offset = d.focalPoint - startPoint;
scale = min(max(1, scale * (d.scale + 13) / 14), 128);
Timer.run(() => setState(() {}));
}

Unity: Ignore collision of a plateform if jump to it from below. Using ContactFilter & rigidBody.Cast()

I am able to avoid a collision between my player and my entire plateform with the use of contactFilter2D.SetLayerMask() + rigidBody2D.Cast(Vector2, contactFilter, ...);
But I don't find a way to avoid the collision only if my player try to acces to the plateform from below it (with a vertical jump).
I'm pretty sure I should use the contactFilter2D.setNormalAngle() (after specify the minAngle and maxAngle) but no matter the size of my angles, I can't pass threw it.
This is how I initialize my contactFilter2D.
protected ContactFilter2D cf;
void Start () {
cf.useTriggers = false;
cf.minNormalAngle = 0;
cf.maxNormalAngle = 180;
cf.SetNormalAngle(cf.minNormalAngle, cf.maxNormalAngle);
cf.useNormalAngle = true;
}
void Update () {
}
I use it with
count = rb.Cast(move, contactFilter, hitBuffer, distance + shellRadius);
Any ideas ? If you want more code, tell me. But I don't think it will be usefull to understand the matter.
unity actualy has a ready made component for this: it is a physics component called "Platform Effector 2D" if you drag and drop it on your platform it will immediately work the way you want, and it has adjustable settings for tweaking the parameters. hope this helps!

GetAssetPreview always returns null for UnityEngine.UI.Image

I have an array of prefabs i want to show a preview of in my custom editor. This works for gameobjects with a mesh renderer, for example the basic quad. However when i try to use AssetPreview.GetAssetPreview(tilePrefab.gameObject); on gameobject with a UnityEngine.UI.Image and a canvas renderer it always returns null.
Below is the part of the code that draws the previews.
public class MapEditor : Editor
{
public override void OnInspectorGUI()
{
for (int prefabIndex = 0; prefabIndex < TileSet.TilePrefabs.Count; prefabIndex++)
DrawIconTexture(prefabIndex, columnCount);
}
private void DrawIconTexture(int prefabIndex, int columnCount)
{
TileBehaviour tilePrefab = TileSet.TilePrefabs[prefabIndex];
Texture iconTexture = AssetPreview.GetAssetPreview(tilePrefab.gameObject);
Rect iconRect = GetIconRect(prefabIndex, columnCount);
if (iconTexture != null)
GUI.DrawTexture(iconRect, iconTexture);
else if (AssetPreview.IsLoadingAssetPreview(tilePrefab.gameObject.GetInstanceID()))
Repaint();
}
}
I know GetAssetPreview loads assets async, that is solved by the repaint. I have also tried
while(iconTexture == null)
iconTexture = AssetPreview.GetAssetPreview(tilePrefab.gameObject);
But that never finishes.
I also tried to use the texture of the Image
if (iconTexture == null)
iconTexture = tilePrefab.GetComponent<Image>().sprite.texture;
But that does not work because the sprite is in an atlas and all of the atlas is shown.
Edit: misread the question. I actually tried to use IsLoadingAssetPreview and IsLoadingAssetPreviews for few hours, without success. I ended up using a sad little trick
if (_previews.All(pair => pair.Value != null)) return;
_previews = GeneratePreviews();
I put that in the Update() loop of my EditorWindow. It's pretty hacky, I'm going to ask Unity if the AssetPreview methods are actually working.
Old answer, irrelevant:
You are not using the while loop and GetAssetPreview correctly.
GetAssetPreview will launch an asynchronous loading of the preview. To know if the preview is fully loaded you need to call AssetPreview.IsLoadingAssetPreview.
A pretty simple and brutal way of doing it (it will block execution) is :
var preview = AssetPreview.GetAssetPreview(item);
while (AssetPreview.IsLoadingAssetPreview(item.GetInstanceID())) {
// Loading
}
As usual, careful with while loops. Note that there is also a AssetPreview.IsLoadingAssetPreviews method with no parameters.
you should just use "using UnityEditor"