Skip to content

Commit

Permalink
Add support for triggers
Browse files Browse the repository at this point in the history
  • Loading branch information
Flowtter committed Nov 30, 2022
1 parent 38ec9c7 commit 3bba303
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 34 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,18 @@ Here is the structure of a basic JSON for a door:
// Physics component (optional)
"collider": {
"radius": 15, // use "radius" to create a circle. Use "width" and "height" to create a rectangle
"offsetX": -15, // collider offset on X
"offsetY": -30, // collider offset on Y
"x": -15, // collider offset on X
"y": -30, // collider offset on Y
"immovable": false, // static or dynamic physic body
"dragX": 0.05, // drag on x = "friction"/velocity slowdown speed
"dragY": 0.05, // drag on y = "friction"/velocity slowdown speed
"collideTilemap": true // enable or disable collision with walls
},
"trigger": {
"width": 15, // radius is not supported for triggers
"height": 15,
"x": -15, // collider offset on X
"y": -30 // collider offset on Y
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions core/client/components/character.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class Character extends Phaser.GameObjects.Container {
this.running = false;
this.chatCircle = undefined;

this.triggers = {};
this.lastTriggers = {};

this.skinPartsContainer = this.scene.add.container(0, 0);
this.skinPartsContainer.setScale(3);
this.add(this.skinPartsContainer);
Expand Down
40 changes: 39 additions & 1 deletion core/client/entity-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ entityManager = {

if (nearestEntity) {
if (nearestEntity === this.previousNearestEntity) return;
if (nearestEntity.actionType === entityActionType.actionable && nearestEntity.gameObject?.trigger) return;

if (!this.previousNearestEntity) {
characterPopIns.createOrUpdate(
Expand Down Expand Up @@ -282,7 +283,7 @@ entityManager = {
if (!entity.gameObject) return undefined;

let mainSprite;
const { collider, sprite, animations, text } = entity.gameObject;
const { collider, sprite, trigger, animations, text } = entity.gameObject;
if (sprite) {
mainSprite = this.spawnSpriteFromConfig(sprite);
gameObject.add(mainSprite);
Expand All @@ -296,6 +297,43 @@ entityManager = {
// configuration: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/arcade-body/
if (collider) this.spawnColliderFromConfig(gameObject, collider);


const overlapEnd = () => {
const dbEntitiy = Entities.findOne(gameObject.getData('id'));
if (!dbEntitiy) return;

if (dbEntitiy.actionType === entityActionType.actionable) {
Entities.update(dbEntitiy._id, { $set: { state: 'off' } });
}
};
const overlapStart = user => {
const id = gameObject.getData('id');
user.triggers[id] = overlapEnd;

if (user.lastTriggers[id]) return;

const dbEntitiy = Entities.findOne(id);
if (!dbEntitiy) return;

if (dbEntitiy.actionType === entityActionType.actionable) {
Entities.update(id, { $set: { state: 'on' } });
}
};

if (trigger && !trigger.radius) {
const user = userManager.getControlledCharacter();

// eslint-disable-next-line no-restricted-syntax, guard-for-in
for (const key in trigger) {
trigger[key] *= entity.gameObject.scale ?? 1;
}

const triggerObject = this.scene.add.rectangle(gameObject.x + trigger.x + trigger.width / 2, gameObject.y + trigger.y + trigger.height / 2, trigger.width, trigger.height);

this.scene.physics.add.existing(triggerObject);
this.scene.physics.add.overlap(user, triggerObject, overlapStart, null, this);
}

// pickable/loots animations
const pickable = entity.actionType === entityActionType.pickable;
if (pickable && mainSprite) {
Expand Down
74 changes: 43 additions & 31 deletions core/client/scenes/scene-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,34 @@ let isSelecting = false;
let selection = {};
let timerResetCopyPaste;

function drawTrigger(collider, gameObject, entity, scale) {
let collision;
if (gameObject.radius) {
// the problem is that the collider is drawn at the center of the entity, but the position is at the top left corner
collision = {
x: gameObject.x + gameObject.radius,
y: gameObject.y + gameObject.radius,
radius: gameObject.radius,
};
} else {
collision = { x: gameObject.x, y: gameObject.y, w: gameObject.width, h: gameObject.height };
}

// eslint-disable-next-line no-restricted-syntax, guard-for-in
for (const key in collision) {
collision[key] *= scale ?? 1;
}
collision.x += entity.x;
collision.y += entity.y;

if (gameObject.radius) {
collider.strokeCircle(collision.x, collision.y, collision.radius);
collider.fillCircle(collision.x, collision.y, collision.radius);
} else {
collider.strokeRect(collision.x, collision.y, collision.w, collision.h);
collider.fillRect(collision.x, collision.y, collision.w, collision.h);
}
}

function compareMouseMovements(currentPosition, lastMousePosition) {
return currentPosition.x === lastMousePosition.x && currentPosition.y === lastMousePosition.y;
Expand Down Expand Up @@ -59,16 +87,16 @@ EditorScene = new Phaser.Class({
Phaser.Scene.call(this, { key: 'EditorScene' });
},

newEntityCollider() {
newEntityCollider(color = 0xff0000) {
const collider = this.add.graphics();
collider.setDefaultStyles({
lineStyle: {
width: 2,
color: 0x00ff00,
color,
alpha: 1,
},
fillStyle: {
color: 0x00ff00,
color,
alpha: 0.25,
},
});
Expand Down Expand Up @@ -98,6 +126,7 @@ EditorScene = new Phaser.Class({
this.marker.setDepth(editorGraphicsDepth);

this.entityCollider = {};
this.entityTrigger = {};

this.areaSelector = this.add.graphics();
this.areaSelector.setDefaultStyles({
Expand Down Expand Up @@ -176,6 +205,10 @@ EditorScene = new Phaser.Class({
val.clear();
});

Object.values(this.entityTrigger).forEach(val => {
val.clear();
});

if (this.mode === editorModes.zones) {
if (this.input.manager.activePointer.isDown && canvasClicked) this.isMouseDown = true;

Expand Down Expand Up @@ -477,35 +510,14 @@ EditorScene = new Phaser.Class({
if (entity.gameObject?.collider) {
if (!this.entityCollider[entity._id]) this.entityCollider[entity._id] = this.newEntityCollider()
const collider = this.entityCollider[entity._id]

if (entity.gameObject.scale < 0) return

var collision;
if (entity.gameObject.collider.radius) {
// the problem is that the collider is drawn at the center of the entity, but the position is at the top left corner
collision = {
x: entity.gameObject.collider.x + entity.gameObject.collider.radius,
y: entity.gameObject.collider.y + entity.gameObject.collider.radius,
radius: entity.gameObject.collider.radius,
}
}
else {
collision = { x: entity.gameObject.collider.x, y: entity.gameObject.collider.y, w: entity.gameObject.collider.width, h: entity.gameObject.collider.height };
}

for (const key in collision) {
collision[key] *= entity.gameObject.scale ?? 1;
}
collision.x += entity.x;
collision.y += entity.y;

if (entity.gameObject.collider.radius) {
collider.strokeCircle(collision.x, collision.y, collision.radius);
collider.fillCircle(collision.x, collision.y, collision.radius);
} else {
collider.strokeRect(collision.x, collision.y, collision.w, collision.h);
collider.fillRect(collision.x, collision.y, collision.w, collision.h);
}
drawTrigger(collider, entity.gameObject.collider, entity, entity.gameObject.scale);
}
if (entity.gameObject?.trigger && !entity.gameObject.trigger.radius) {
if (!this.entityTrigger[entity._id]) this.entityTrigger[entity._id] = this.newEntityCollider(0x4444aa)
const trigger = this.entityTrigger[entity._id]
if (entity.gameObject.scale < 0) return
drawTrigger(trigger, entity.gameObject.trigger, entity, entity.gameObject.scale);
}
});
}
Expand Down
11 changes: 11 additions & 0 deletions core/client/user-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,17 @@ userManager = {
} else this.controlledCharacter.setAnimationPaused(true);

if (moving || this.controlledCharacter.wasMoving) {
const lastTriggersArray = Object.keys(this.controlledCharacter.lastTriggers);
const triggersArray = Object.keys(this.controlledCharacter.triggers);
const outersection = lastTriggersArray.filter(trigger => !triggersArray.includes(trigger));
for (const trigger of outersection) {
this.controlledCharacter.lastTriggers[trigger]();
}


this.controlledCharacter.lastTriggers = this.controlledCharacter.triggers;
this.controlledCharacter.triggers = {};

this.scene.physics.world.update(time, delta);
networkManager.sendPlayerNewState(this.controlledCharacter);
this.stopInteracting();
Expand Down

0 comments on commit 3bba303

Please sign in to comment.