gpt4 book ai didi

java - 碰撞 - 识别物体何时停止碰撞

转载 作者:行者123 更新时间:2023-12-01 11:57:51 36 4
gpt4 key购买 nike

我的意思是,当我与实体的侧面碰撞并想要跳跃时,我无法向右/向左移动,因为当我与右侧/左侧的实体碰撞时,我有一个标志可以防止这种情况发生,例如所以:

img

这是我用来检测碰撞的代码:

public void onCollision(Wrapper wrapper) {
if (horizontal_velocity == 0 && vertical_velocity == 0) {
return;
}

Entity e1 = wrapper.thisEntity; //the object we are controlling
Entity e2 = wrapper.otherEntity; //the object we are impacting with

Rectangle rect1 = wrapper.thisEntityRectangle;
Rectangle rect2 = wrapper.otherEntityRectangle;

int e1y = (int) rect1.getY(), e1x = (int) rect1.getX(), e1w = (int) rect1.getWidth(), e1h = (int) rect1.getHeight();
int e2y = (int) rect2.getY(), e2x = (int) rect2.getX(), e2w = (int) rect2.getWidth(), e2h = (int) rect2.getHeight();

e1x += e1w / 2;
e1w /= 2;
e1y += e1h / 2;
e1h /= 2;


//horizontal interaction -- x

/* ---+\\\\\\+---
* |------|
* | |
* e1 | e2 | e1
* | |
* |------|
* ---+\\\\\\+---
*/

boolean touchingSide = false;

if(e1y > e2y && e1y < e2y + e2h) {
//touchingSide = true;
if(e1x > e2x - e1w && e1x < e2x) { //going right || hitting left side
collisionsHappening.put(wrapper.otherEntity.getID(), "right");
canMoveRight = false;
horizontal_velocity = 0;
setX(e2x - e1w*2);
}

if(e1x < e2x + e2w + e1w && e1x > e2x) { //going left || hitting right side
collisionsHappening.put(wrapper.otherEntity.getID(), "left");

canMoveLeft = false;
horizontal_velocity = 0;
setX(e2x + e2w);
}
}

//vertical interaction -- y

/*
* \| e1 |\
* \+--+------+--+\
* \\\\| |\\\\
* \\\\| e2 |\\\\
* \\\\| |\\\\
* \+--+------+--+\
* \| e1 |\
*
*/

if(e1x > e2x - e1w && e1x < e2x + e2w && !touchingSide) {
if(e1y + e1h > e2y && e1y < e2y) { //going down || hitting top side
collisionsHappening.put(wrapper.otherEntity.getID(), collisionsHappening.get(wrapper.otherEntity.getID()) + "|top");
setY(e2y - e1h * 2);
vertical_velocity = 0;
//readyNextTurn = true;

isFalling = false;
onGround = true;
}
if(e1y - e1h < e2y + e2h && e1y > e2y) { //going up || hitting bottom side
collisionsHappening.put(wrapper.otherEntity.getID(), collisionsHappening.get(wrapper.otherEntity.getID()) + "|bottom");
setY(e2y + e2h + e1h);
vertical_velocity = 0;
//readyNextTurn = true;
isFalling = false;
onGround = true;

}
}
}

..代码受 canMoveRightcanMoveLeft 标志影响的地方:

public void key(int keyCode) {
try {
onEdge();

switch (keyList.get(keyCode)) {

...

case MOVE_RIGHT:
for(Entity e : objectsCollidingWith) { //check if still colliding, if not, reset variable canMoveLeft inorder to not impair movement
if(collisionsHappening.get(e.getID()) == "right") {
canMoveRightNextFrame = true;
}
}
canMoveLeft = true;
if (!canMoveRight && !canMoveRightNextFrame) break;

if(canMoveRightNextFrame) {
canMoveRightNextFrame = false;
System.out.println(canMoveRightNextFrame);
}

if (horizontal_velocity == 0) {
horizontal_velocity = getXDisplacement();
}
changeX(horizontal_velocity);
direction = "right";
//horizontal_velocity = 0;
break;
case MOVE_LEFT:
for(Entity e : objectsCollidingWith) { //check if still colliding, if not, reset variable canMoveLeft inorder to not impair movement
if(collisionsHappening.get(e.getID()) == "left") {
canMoveLeftNextFrame = true;
}
}
canMoveRight = true;
if (!canMoveLeft && !canMoveLeftNextFrame) {
break;
}

canMoveLeftNextFrame = canMoveLeftNextFrame ? true : false; //if true, make false

if (horizontal_velocity == 0) {
horizontal_velocity = getXDisplacement();
}
changeX(-horizontal_velocity);
direction = "left";
//horizontal_velocity = 0;
break;
case JUMP:
jump();
}
} catch (NullPointerException e) {
//ignore - a key with no action pressed
}
}
<小时/>

我尝试过的

当我寻找冲突时 - 不会像上面的代码那样对它们使用react - 我尝试实现一个 HashMap,其中我将一个字符串 - "left""right" - 到键 Entity.getID() ,它返回一个唯一的名称,如下所示(相关代码行之后是 // <<< ):

public Wrapper[] collisions(Entity thisEntity) {
ArrayList<Wrapper> wrappers = new ArrayList<Wrapper>();
Player p = null;
boolean isPlayer = thisEntity instanceof Player;
boolean onGround = false;

if (isPlayer) {
p = (Player) thisEntity;
}
try {
for (Entity e : getLevel().getEntities()) {
if (!thisEntity.equals(e)) {
collisionsHappening.put(e.getID(), ""); // <<<
objectsCollidingWith.add(e); // <<<
if (thisEntity.getRect().intersects(e.getRect())) {
wrappers.add(new Wrapper(thisEntity, e, thisEntity.getRect(), e.getRect(),
thisEntity.getRect().intersection(e.getRect())));

onGround = true;
//collisionsHappening.put(e.getID(), true);
//System.out.println("collision between " + e.getID() + " + " + thisEntity.getID());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (isPlayer) {
p.isTouching = onGround;
if (onGround) {
//System.out.println(onGround);
}

}
//Entity[] result = list.toArray(new Entity[1]);
return wrappers.toArray(new Wrapper[0]);
}

该系统依赖于在碰撞停止后保留标志 1 帧,以便删除代码行中的标志 canMoveRightcanMoveLeft

for(Entity e : objectsCollidingWith) {  //check if still colliding, if not, reset variable canMoveLeft inorder to not impair movement
if(collisionsHappening.get(e.getID()) == "left") {
canMoveLeftNextFrame = true;
}
}
canMoveRight = true;
if (!canMoveLeft && !canMoveLeftNextFrame) {
break;
}

if(canMoveLeftNextFrame) {
canMoveLeftNextFrame = false; //if true, make false
}

...

...对于 canMoveRight 标志也是如此...

<小时/>

但是,这不起作用,并且在“抓取”实体的边缘后我仍然无法在跳跃中移动,除非我朝相反方向移动以“重置”所需方向的标志(行:case MOVE_RIGHT: ... canMoveLeft = true;case MOVE_LEFT: ... canMoveRight = true; ),如动画所示。

所以,总结一下:

  • 如何使该系统正常运行?
  • 有没有更有效/更好的方法来做这种事情?
  • 您建议我重做碰撞吗?

谢谢。

最佳答案

对于比贪吃蛇更高级的游戏来说,用事件驱动的方式来解决这个问题实际上是不可能的。我建议您关注更新每个实体的简单更新循环。然后每个实体更新自己的速度和位置。然后检查碰撞并处理响应。关键事件处理程序不应该有任何逻辑,而只是更改实体可以轮询的标志。

至于碰撞和响应部分,这是简单平台游戏引擎的核心所在,并且有许多不同的方法。在现成的物理引擎的现代世界中,例如Box2D,你可以简单地让物理系统处理事情。但从事情的声音来看,你并不是在寻找那个,你想要的是我所说的基于逻辑的物理学。

如果您的世界和实体由轴对齐的框组成,您可以将每个实体的水平和垂直运动分成两个离散的步骤。对于每个轴,每个对象都会尝试尽可能远地移动(取决于速度和碰撞),如果对象撞到某物,则会生成碰撞事件并将该轴上的速度设置为零。对另一个轴重复此操作,您将拥有一个简单的平台游戏引擎。对于此方法,您需要仔细处理由于 float 值误差而导致的两个对象接触的状态。我建议使用整数进行碰撞检测(以屏幕坐标的比例)。

如果您希望拥有一个不限于轴对齐框的环境和实体,那么您将必须变得更加复杂,并且不再依赖于简单地处理 X 然后 Y 移动来为您提供诸如框滑动之类的东西在地板上或墙上。在这种情况下,我建议您跟踪您的实体站立或行走的表面,以便您可以在每种状态下以不同的方式处理它们的运动。当它们在空中时,进行正常运动,但是当它们在某个表面上时,运动被限制为水平运动,并调整垂直位置以将它们保持在表面上。然后,您需要检测它们何时改变状态。

我希望您觉得这有帮助。事实证明,这对谷歌来说并不是一个容易的话题。 (更新循环、碰撞检测、运动物理、数值积分和碰撞响应的几何形状都很容易通过 Google 搜索)。大多数程序员似乎只是采取不断摆弄它直到它起作用的方法,因此它永远不会得到很好的记录。

附注隐式欧拉积分方法适用于大多数游戏。

关于java - 碰撞 - 识别物体何时停止碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28288810/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com