-
Hi, everyone. Please advise. I want to detect if an actor is on the ground, because I want to make the player jumpable only when he is on the ground. sample code
Physics.gravity = Vector.Down.scale(300);
import {
Actor,
CollisionType,
Color,
Engine,
PreCollisionEvent,
Scene,
Vector,
} from "excalibur";
export class GameScene extends Scene {
onInitialize(engine: Engine): void {
const ground1 = new Actor({
pos: new Vector(200, 700),
width: 300,
height: 200,
color: Color.Cyan,
collisionType: CollisionType.Fixed,
});
engine.add(ground1);
const ground2 = new Actor({
pos: new Vector(400, 400),
width: 100,
height: 600,
color: Color.Magenta,
collisionType: CollisionType.Fixed,
});
engine.add(ground2);
const player = new Actor({
x: engine.halfDrawWidth,
y: engine.halfDrawHeight,
width: 20,
height: 20,
color: Color.Chartreuse,
collisionType: CollisionType.Active,
});
engine.add(player);
player.vel = new Vector(30, 0);
player.on("precollision", (event: PreCollisionEvent): void => {
console.log(event.side);
});
}
} result
problemI get the log that repeats Therefore, I cannot detect if an actor is on the ground as following code. let isOnGround = false;
player.on("precollision", (event: PreCollisionEvent): void => {
if (event.side === Side.Bottom) {
isOnGround = true;
} else {
isOnGround = false;
}
}); Does anyone knows good solution? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Here are all code. https://github.com/tenpaMk2/excalibur-examples/tree/main/examples/detect-ground |
Beta Was this translation helpful? Give feedback.
-
@tenpaMk2 This is a good question! There are a couple tricks that can be used to detect on ground in a situation like this:
export class GameScene extends Scene {
playerOnGround = false;
playerSideCollisions: Side[] = [];
onPreUpdate() {
playerSideCollisions.length = 0; // clear last frame's side collisions
}
...
isPlayerOnGround() {
return playerSideCollisions.includes(Side.Bottom);
}
onInitialize() {
...
player.on("postcollision", (event: PostCollisionEvent): void => {
playerSideCollisions.push(event.side);
});
engine.input.pointers.primary.on("down", (event: PointerEvent): void => {
if (this.isPlayerOnGround()) player.vel = player.vel.add(new Vector(0, -100)); // jump!!
});
}
const playerGroup = ex.CollisionGroupManager.create('player'); // things in the same group do not collide
const player = new Actor({
x: engine.halfDrawWidth,
y: engine.halfDrawHeight,
width: 20,
height: 20,
color: Color.Chartreuse,
collisionType: CollisionType.Active,
collisionGroup: playerGroup
});
const groundColliderActor = new ex.Actor({
x: 0,
y: offsetBelowPlayer,
width: playerWidth,
height: 32,
color: ex.Color.Green, // color there just to visualize where the collider is
collisionType: ex.CollisionType.Passive,
collisionGroup: playerGroup
});
let activeGroundCollisions = 0;
groundColliderActor.on('collisionstart', () => {
activeGroundCollisions++;
});
groundColliderActor.on('collisionend', () => {
activeGroundCollisions--;
});
player.addChild(groundColliderActor);
const isPlayerOnGround = () => {
return activeGroundCollisions > 0;
}
const floorActors: ex.Actor[] = [...];
const onGround = () => {
for (let floor of floorActors) {
const hit = floor.collider.get().rayCast(
new ex.Ray(player.pos, ex.Vector.Down),
100); // length to cast
if (hit) {
return true;
}
return false;
}
} |
Beta Was this translation helpful? Give feedback.
@tenpaMk2 This is a good question!
There are a couple tricks that can be used to detect on ground in a situation like this:
Side.Bottom
is in the list of sides that collided that frame you are on the ground.