I'm trying to use Matter.Query.region
to see if the character in my game is grounded. But, when I try to run region
with a bounds object that I created (displayed with the dots shown in the game), it doesn't come up with any collisions even though it is clearly intersecting other bodies.
Code:
let Engine = Matter.Engine,
Runner = Matter.Runner,
World = Matter.World,
Bodies = Matter.Bodies,
Body = Matter.Body,
Composite = Matter.Composite;
let engine;
let boxA;
let boxB;
let platforms = [];
function setup() {
createCanvas(550, 400);
// create an engine
engine = Engine.create();
// create two boxes and a ground
boxA = Bodies.rectangle(275, 200, 80, 80, {
mass: 20
});
platforms.push(boxA);
boxB = Bodies.rectangle(300, 50, 80, 80, {
mass: 20
});
Body.setInertia(boxB, Infinity);
ground = Bodies.rectangle(250, 410, 810, 60, {
isStatic: true
});
platforms.push(ground);
// add all of the bodies to the world
World.add(engine.world, [boxA, boxB, ground]);
let runner = Runner.create();
Runner.run(runner, engine);
}
// Using p5 to render
function draw() {
let add = Matter.Vector.add; // alias
let leeway = {x: 0, y: 30}
let topLeft = {x: boxB.position.x - 40, y: boxB.position.y + 40}
let topRight = add(topLeft, {x: 80, y: 0});
let bottomLeft = add(topLeft, leeway);
let bottomRight = add(topRight, leeway);
let bounds = Matter.Bounds.create(topLeft, topRight, bottomRight, bottomLeft);
let query = Matter.Query.region(platforms, bounds);
console.log(Matter.Bounds.overlaps(bounds, boxA.bounds), query);
background(51);
keyDown();
drawShape(boxA);
drawShape(boxB);
drawShape(ground, 127);
push();
// Show bounds
stroke('purple');
strokeWeight(10);
point(topLeft.x, topLeft.y);
point(topRight.x, topRight.y);
point(bottomLeft.x, bottomLeft.y);
point(bottomRight.x, bottomRight.y);
pop();
}
function drawShape(body, color = 225) {
beginShape();
fill(color);
for (let vertice of body.vertices) {
vertex(vertice.x, vertice.y);
}
endShape();
}
function keyPressed() {
let jumpHeight = 14;
if (keyCode === UP_ARROW) {
Body.setVelocity(boxB, {x:boxB.velocity.x, y:-jumpHeight})
}
}
function keyDown() {
let velocity = 12;
let targetX = boxB.velocity.x;
if (keyIsDown(RIGHT_ARROW)) {
targetX = velocity;
} else if (keyIsDown(LEFT_ARROW)) {
targetX = -velocity;
} else {
targetX = 0;
}
targetX = lerp(boxB.velocity.x, targetX, 0.1);
Body.setVelocity(boxB, {x: targetX, y: boxB.velocity.y});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js" integrity="sha512-5T245ZTH0m0RfONiFm2NF0zcYcmAuNzcGyPSQ18j8Bs5Pbfhp5HP1hosrR8XRt5M3kSRqzjNMYpm2+it/AUX/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Full code: https://replit.com/@CrazyVideoGamer/MatterQueryregion-not-working#sketch.js
By the way, the character is the variable boxB
, and you can move with the arrow keys.
The bounds object doesn't appear to be properly created. The purple p5 vertices you're rendering may be giving you a false sense of confidence, since those aren't necessarily related to what MJS sees.
It's actually a pretty simple fix, passing an array of vertices instead of individual arguments:
let bounds = Matter.Bounds.create([topLeft, topRight, bottomRight, bottomLeft]);
// ^ ^
I wound up cleaning things up a bit in the process of debugging and made the collision easier to visualize without the console. Feel free to use some of this code if you need or just make the one change as you see fit.
const {Engine, Runner, Composite, Bodies, Body} = Matter;
let engine;
let boxA;
let boxB;
const platforms = [];
function setup() {
createCanvas(550, 400);
engine = Engine.create();
// create two boxes and a ground
boxA = Bodies.rectangle(275, 200, 80, 80, {
mass: 20
});
platforms.push(boxA);
boxB = Bodies.rectangle(300, 50, 80, 80, {
mass: 20
});
Body.setInertia(boxB, Infinity); // TODO remove for realism
ground = Bodies.rectangle(250, 410, 810, 60, {
isStatic: true
});
platforms.push(ground);
Composite.add(engine.world, [boxA, boxB, ground]);
Runner.run(Runner.create(), engine);
}
function draw() {
const {x, y} = boxB.position;
const vertices = [
// FIXME hardcoded values for now...
{x: x - 40, y: y + 40},
{x: x + 40, y: y + 40},
{x: x + 40, y: y + 50},
{x: x - 40, y: y + 50},
];
const bounds = Matter.Bounds.create(vertices, boxB);
// return valaue holds the collided platform(s)
const collisions = Matter.Query.region(platforms, bounds);
background(51);
keyDown();
drawShape(boxA);
drawShape(boxB);
drawShape(ground, 127);
push();
// Show bounds collision
stroke(collisions.length ? 'red' : 'purple');
strokeWeight(10);
vertices.forEach(({x, y}) => point(x, y));
pop();
}
function drawShape(body, color=225) {
beginShape();
fill(color);
body.vertices.forEach(({x, y}) => vertex(x, y));
endShape();
}
function keyPressed() {
const jumpHeight = 14;
if (keyCode === UP_ARROW) {
Body.setVelocity(boxB, {x: boxB.velocity.x, y: -jumpHeight})
}
}
function keyDown() {
const velocity = 12;
let targetX = 0;
if (keyIsDown(RIGHT_ARROW)) {
targetX = velocity;
} else if (keyIsDown(LEFT_ARROW)) {
targetX = -velocity;
}
targetX = lerp(boxB.velocity.x, targetX, 0.1);
Body.setVelocity(boxB, {x: targetX, y: boxB.velocity.y});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.4/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.20.0/matter.min.js"></script>