Matter.js 防止鼠标拖动,同时仍然能够与其他对象发生碰撞 我的尝试:问题^^

问题描述

在创建我自己版本的 Matter.js slingshot demo[source] 时,我在尝试防止弹丸在发射后被拖动时卡住了.

我的尝试:

创建 3 个 collisionFilter 类别;

  1. 0x0001static:地面、平台等
  2. 0x0002drag:与鼠标交互的项目
  3. 0x0004nodrag不能与鼠标交互的项目,但会与其他所有东西发生碰撞

这很好用,一切都相互碰撞,而且我只能拖动弹丸(drag),而不能拖动目标(nodrag)。

所以我的下一个挑战是在发射后将弹丸从 drag 切换到 nodrag。否则,您可以抓住射弹并将其用作破坏球
因此,就在我向弹性体添加新射弹之前,我尝试将 collisionFilter 切换为 nodrag,如下所示:

Events.on(engine,'afterUpdate',function() {

    // If Rock is outside drag-range
    if (mouseConstraint.mouse.button === -1 && (rock.position.x > dragborder_x || rock.position.y < dragborder_y)) {

        rock.collisionFilter = { category: cat.nodrag };
        ...

问题^^

不幸的是,这可以防止射弹与所有物体发生碰撞,甚至是墙壁 (static)。即使具有 nodrag 的目标仍然与墙壁发生碰撞。所以我不知道为什么射弹在切换到 nodrag 后停止碰撞。

(tl;dr)
正在寻找一些指导以阻止射弹在发射后可拖动。


简化示例

  • 切换第 72 行以查看上述问题

// Statics
const vw = window.innerWidth;
const vh = window.innerHeight;
var Engine = Matter.Engine,Render = Matter.Render,Runner = Matter.Runner,Composites = Matter.Composites,Events = Matter.Events,Constraint = Matter.Constraint,MouseConstraint = Matter.MouseConstraint,Mouse = Matter.Mouse,World = Matter.World,Bodies = Matter.Bodies;
const cat = {
    static:    0x0001,nodrag:    0x0002,drag:      0x0004
};

// Create world
var engine = Engine.create();
var world = engine.world;

// Create render
var render = Render.create({
    element: document.body,engine: engine,options: {
        width: vw,height: vh,wireframes: false,showAngleIndicator: false
    }
});
// render.on()
Render.run(render);

// Create runner
var runner = Runner.create();
Runner.run(runner,engine);

// Body consts
const rock_x = vw * .20;
const rock_y = vh * .66;
const rockOptions = { 
    density: 0.01,collisionFilter: {
        category: cat.drag
    }
};
const gift = {
    render: {
        sprite: {}
    },collisionFilter: {
        category: cat.nodrag
    }
};

// Add Static bodies
var ground   = Bodies.rectangle(vw * .5,vh * .9,vw * .9,42,{ isstatic: true,render: { fillStyle: '#060a19' } });
var rock     = Bodies.polygon(rock_x,rock_y,8,15,rockOptions);
var anchor   = { x: rock_x,y: rock_y };
var elastic  = Constraint.create({ pointA: anchor,bodyB: rock,stiffness: 0.09,render: { linewidth: 1 } });
var wall     = Composites.stack(vw * .66,2,(vh * .4) / 15,1,(x,y) => Bodies.rectangle(x,y,gift));
var platform = Bodies.rectangle(vw * .75,vh * .6,210,21,render: { fillStyle: '#060a19' },collisionFilter: { category: cat.static } });
var pyramid  = Composites.pyramid(vw * .30,11,gift));

World.add(engine.world,[ ground,pyramid,platform,wall,rock,elastic ]);

// Rock drag
const dragborder_x = rock_x + 20;
const dragborder_y = rock_y - 20;
Events.on(engine,function() {

    // If Rock is outside drag-range
    if (mouseConstraint.mouse.button === -1 && (rock.position.x > dragborder_x || rock.position.y < dragborder_y)) {

        // Failed attempt
        // rock.collisionFilter = { category: cat.nodrag };

        // Add new Rock
        rock = Bodies.polygon(rock_x,7,rockOptions);
        World.add(engine.world,rock);

        // Re-bind elastic
        elastic.bodyB = rock;
    }
});

// Mouse control
var mouse = Mouse.create(render.canvas);
var mouseConstraint = MouseConstraint.create(engine,{
    mouse: mouse,constraint: {
        stiffness: 0.2,render: {
            visible: false
        }
    }
});

// Add mouse
World.add(world,mouseConstraint);
render.mouse = mouse;

// Prevent mouse-drag
mouseConstraint.collisionFilter.mask = cat.static | cat.drag;

// Run
Engine.run(engine);
Render.run(render);
<script src="https://cdn.jsdelivr.net/npm/matter-js@0.16.1/build/matter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<Meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no,minimal-ui">

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)