Я использую библиотеку javascript вещество js, чтобы заменить курсор на холсте HTML веществом js - тело .
Тело (форма круга) следует за курсором, используя ограничение с жесткостью 0,1 и затуханием 1.
Проблема, с которой я столкнулся, заключается в том, что столкновение воспринимается странным образом. Если я сожму достаточно, я смогу заставить объект-курсор проходить через пятна, которые закрыты другими (stati c) объектами.
Я пытался изменить жесткость во время CollisionActive. Лучшее поведение я получил, сбросив положение тела, чтобы сохранить фиксированное расстояние до сталкивающегося объекта. Все еще возможно покачиваться с помощью курсора.
Я также нашел эту связанную проблему:
Предотвращение силового перемещения тел через другие тела с помощью Matter JS
Однако первое решение, похоже, не дало результата. Я мог бы заморозить тело курсора, если курсор находится слишком далеко, но это может создать для пользователя ситуацию с потерянным курсором ...
Это был лучший подход, который я мог найти:
// create engine
var engine = Matter.Engine.create(),
world = engine.world;
world.gravity.y = 0;
// create renderer
var render = Matter.Render.create({
element: document.body,
engine: engine,
options: {
width: 400,
height: 400,
background: "#00FFFF",
wireframes: false,
showAngleIndicator: true,
}
});
Matter.Render.run(render);
// create runner
var runner = Matter.Runner.create();
Matter.Runner.run(runner, engine);
for (var i = 0; i < (new Date()).getMilliseconds(); ++i) Matter.Common.random(10, 30); //randomize random()
var ran = 0;
Matter.World.add(world, Matter.Composites.stack(10, 10, 5, 2, 20, 20, function(x, y) {
ran = Matter.Common.random(10, 30);
return Matter.Bodies.circle(x, y, ran, {
isStatic: true,
restitution: 1,
friction: 1,
frictionAir: 1,
frictionStatic: 1,
inertia: Infinity,
render: {
fillStyle: "#" + Math.floor(Math.random() * 16777215).toString(16)
},
label: "target",
radius: ran,
});
}));
var paddle = Matter.Bodies.circle(0, 0, 30, {
mass: 1,
isStatic: false,
restitution: 1,
friction: 0,
inertia: Infinity,
render: {
fillStyle: "#000000"
},
label: "paddle",
radius: 30,
});
Matter.World.add(world, paddle);
function posDif(a, b, f = 1) {
return {
x: f * (a.position.x - b.position.x),
y: f * (a.position.y - b.position.y)
};
}
Matter.Events.on(engine, "collisionActive", (event) => {
for (var o of event.pairs) {
if (o.bodyA == paddle && o.bodyB.label == "target") {
var TgtDist = o.bodyB.radius + paddle.radius;
var diff = posDif(o.bodyB, paddle);
var ang = Math.atan2(diff.x, diff.y);
Matter.Body.setPosition(paddle, {
x: o.bodyB.position.x - TgtDist * Math.sin(ang),
y: o.bodyB.position.y - TgtDist * Math.cos(ang)
});
con.stiffness = 0.01;
}
if (o.bodyB == paddle && o.bodyA.label == "target") { //same with bodyA for bodyB
var TgtDist = o.bodyA.radius + paddle.radius;
var diff = posDif(o.bodyA, paddle);
var ang = Math.atan2(diff.x, diff.y);
Matter.Body.setPosition(paddle, {
x: o.bodyA.position.x - TgtDist * Math.sin(ang),
y: o.bodyA.position.y - TgtDist * Math.cos(ang)
});
con.stiffness = 0.01;
}
}
});
Matter.Events.on(engine, "collisionEnd", (event) => {
for (var o of event.pairs) {
if (o.bodyA == paddle || o.bodyB == paddle)
con.stiffness = 0.1;
}
});
var mouse = Matter.Mouse.create(render.canvas),
mouseConstraint = Matter.MouseConstraint.create(engine, {
mouse: mouse,
constraint: {
angularStiffness: 0.1,
render: {
visible: false
}
}
});
var con = Matter.Constraint.create({
pointA: mouse.position,
bodyB: mouseConstraint.body = paddle,
pointB: {
x: mouse.position.x - paddle.position.x,
y: mouse.position.y - paddle.position.y
},
stiffness: 0.1,
damping: 1,
render: {
visible: false
},
});
Matter.World.add(world, con);
Matter.World.add(world, mouseConstraint);
// keep the mouse in sync with rendering
render.mouse = mouse;
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.14.2/matter.min.js"></script>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="matter.min.js"></script>
<style>
body {
cursor: none;
}
</style>
<title>Document</title>
</head>
<body></body>
</html>
Есть ли способ получить естественное поведение курсора при столкновении, как я описал выше? Или это потребовало бы непрерывного обнаружения столкновений (CCD), которое еще не полностью поддерживается материей js?