Javascript 如何在ECS模式下处理冲突?

Javascript 如何在ECS模式下处理冲突?,javascript,typescript,game-engine,entity-component-system,Javascript,Typescript,Game Engine,Entity Component System,我正在用typescript和ECS模式制作一个游戏。但我不明白如何处理实体之间的冲突。 我有实体Player和一组组件: LayerComponent-组件,它保留用于渲染的层的名称 位置组件-保持位置的组件 AppearanceComponent-组件,保留渲染选项 BoxColliderComponent-component,用于保持碰撞句柄的AABB大小 此外,我还有实体敌人,具有相同的组件集。这些实体在LayerComponent中的值不同。 层组件中的玩家实体保留玩家值,敌人实体

我正在用typescript和ECS模式制作一个游戏。但我不明白如何处理实体之间的冲突。 我有实体
Player
和一组组件:

  • LayerComponent-组件,它保留用于渲染的层的名称
  • 位置组件-保持位置的组件
  • AppearanceComponent-组件,保留渲染选项
  • BoxColliderComponent-component,用于保持碰撞句柄的AABB大小
此外,我还有实体
敌人
,具有相同的组件集。这些实体在
LayerComponent
中的值不同。
层组件中的
玩家
实体保留
玩家
值,
敌人
实体保留
敌人

我不知道如何处理这些实体之间的冲突。这些实体不应相互移动

目前,我已经创建了system
PlayerPosition
,它处理实体间的碰撞和块移动 使用
BoxColliderComponent
。但我认为这是错误的,因为碰撞必须在它们自己的系统中处理

PlayerPosition的代码

从“ecs”导入{System};
从“游戏”导入{ecs,EntityType};
从'services/Vector2.service'导入Vector2,{IVector2};
从“services/mouse.service”导入MouseService;
从“常数/层”导入传送带;
从“实体/敌人”输入敌人;
接口接口{
职位:IVector2;
高度:数字;
宽度:数字;
}
导出默认类PlayerPositionSystem扩展系统{
只读ctx:CanvasRenderingContext2D;
只读实体:EntityType[]=[];
专用只读鼠标:MouseService=new MouseService();
构造函数(ctx:CanvasRenderingContext2D){
超级();
this.ctx=ctx;
}
加法(实体:EntityType):void{
if(本测试(实体)){
这个。实体。推(实体);
}否则{
console.warn(`entity'${entity.id}'没有必要的组件`);
}
}
测试(实体:EntityType):布尔值{
const position=entity.components.position;
返回!!位置;
}
更新(实体:EntityType):无效{
常量组件=entity.components.position;
const colliderComponent=entity.components.boxCollider;
const layerComponent=entity.components.layer;
如果(!component | | |!colliderComponent | |!layerComponent){
返回;
}
if(layerComponent.props.layer!==ELayers.player){
返回;
}
const mouseCoordinates=this.mouse.getmousecoordinates();
const{position,velocity}=component.props;
常量距离=鼠标坐标。距离(位置);
常数deltaVector=鼠标坐标。减法(位置);
常数反演距离=1/距离;
常数方向=新矢量2(
deltaVector.x*反演距离,
deltaVector.y*反演距离
);
const newPosition=position.addition(
新矢量2(
距离>5?方向x*速度:0,
距离>5?方向。y*速度:0
)
);
常量currentObject:IIntersect={
位置:新矢量2(newPosition.x,newPosition.y),
高度:colliderComponent.props.size.y,
宽度:colliderComponent.props.size.x,
};
for(此.entities的常量对象){
如果(对象===实体){
继续;
}
const itemComponents=object.components;
常量项目位置=
itemComponents.position&&itemComponents.position.props;
常量项框对撞机=
itemComponents.boxCollider&&itemComponents.boxCollider.props;
如果(!itemPosition | |!itemBoxCollider){
继续;
}
常数项:IIntersect={
…项目位置,
高度:itemBoxCollider.size.y,
宽度:itemBoxCollider.size.x,
};
if(此.intersect(currentObject,item)){
const itemLayer=object.components.layer;
if(itemLayer&&itemLayer.props.layer===ELayers.敌军){
object.remove();
const canvas=this.ctx.canvas;
设x=Math.random()*canvas.width-100;
x=x<0?0:x;
设y=Math.random()*canvas.height-100;
y=y<0?0:y;
加数(敌方({速度:3,位置:新矢量2(x,y)});
}
设x=newPosition.x;
设y=newPosition.y;
如果(
这是交集(
{
…当前对象,
位置:新矢量2(x,位置y),
},
项目
)
) {
x=位置x;
}
如果(
这是交集(
{
…当前对象,
位置:新矢量2(位置x,y),
},
项目
)
) {
y=位置y;
}
newPosition.set(新向量2(x,y));
}
}
setProperties({position:newPosition});
}
相交(对象:IIntersect,对象2:IIntersect):布尔值{
常量{位置:pos1,高度:h1,宽度:w1}=对象;
常量{位置:pos2,高度:h2,宽度:w2}=object2;
返回(
pos1.x+w1>pos2.x&&
pos2.x+w2>pos1.x&&
pos1.y+h1>pos2.y&&
pos2.y+h2>pos1.y
);
}
}

我不知道是否存在错误或此代码是否正常工作,因此我假设您的问题严格来说是关于将碰撞检测系统的代码放在何处:

在这种情况下,你必须考虑碰撞检测系统和移动系统之间的相互作用。大多数情况下,这种方法类似于

1 - Apply movement without taking collisions into account
2 - Detect collisions
3 - Adjust the movement you made depending on the collisions you just detected
所以,既然你的碰撞检测和你的运动系统紧密结合在一起,我觉得把它放在里面是有意义的。然而,仍然隔离碰撞检测系统可能是一个好主意,因此您可以