- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试实现基本的碰撞检测我正在开发基于体素的 3D Java 游戏。我正在尝试实现来自该网站的算法: 奥 git _a,但我似乎无法做对。我的问题就是,他所说的“将球员位置转变为体素空间'。我应该将玩家的坐标四舍五入到最近的 block ,以便玩家所在的体素是一个玩家的中心在哪里?在我的游戏中玩家目前是一个体素大小的立方体。
该网站上的人写道,他只需要检查一个碰撞体素。但如果我只检查中心的体素玩家的中心在,那么玩家的中心需要在他与物体碰撞之前将它们相交。这不应该是就这样吧?如果玩家的中心位于非 Activity 体素,但玩家立方体的一部分相交一个活跃的体素,我应该检查哪个体素?
我意识到这段文字很令人困惑,但我希望你能明白我的问题。如果您想查看一些代码,这里是我的 CollisionHandler 类:(由于我遇到的问题,它还没有真正遵循上面站点中的算法。到目前为止,它只关心沿 x 轴的碰撞)
public class CollisionHandler {
private static final float COLLISION_TOLERANCE = 0.4f;
private boolean xCol, yCol, zCol = false;
public void handleCollisions(ChunkManager chunkManager,
FPCameraController player, float delta) {
Vector3D playerPos = player.getPosition();
Vector3D collision = findCollisionVector(player, chunkManager);
if (collidesWithWorld()) {
if (!(player.isFalling() && isGrounded(playerPos, chunkManager))) {
player.setCollisionVector(collision);
player.translateX(-playerPos.subtract(playerPos.round()).getX());
}else{
//123456
}
} else {
if (player.isFalling()) {
if (isGrounded(playerPos, chunkManager)) {
float overlap = getYOverlap(player, chunkManager);
player.translateY(overlap);
player.setYSpeed(0);
player.setIsFalling(false);
} else {
player.applyGravity(delta);
}
} else {
if (!isGrounded(playerPos, chunkManager)) {
player.setIsFalling(true);
player.applyGravity(delta);
}
}
}
}
private boolean collidesWithWorld() {
return xCol || yCol || zCol;
}
/*
* Returns a collision vector. Dot with velocity and then subtract it from
* the player velocity.
*/
private Vector3D findCollisionVector(FPCameraController player,
ChunkManager chunkManager) {
Vector3D playerPos = player.getPosition();
Vector3D distance = playerPos.subtract(playerPos.floor()).abs();
Vector3D collisions = new Vector3D(1, 1, 1);
float xDirection = (getCollisionDirection(distance.getX()));
// float yDirection = (getCollisionDirection(distance.getY()));
// float zDirection = (getCollisionDirection(distance.getZ()));
try {
Vector3D collision = getCollisionNormal(chunkManager, playerPos,
xDirection, 'x');
if (collision != null) {
collisions = collision;
xCol = true;
} else {
xCol = false;
}
// collision = getCollisionNormal(chunkManager, playerPos,
// yDirection,
// 'y');
// if (collision != null) {
// collisions.cross(collision);
// yCol = true;
// } else {
// yCol = false;
// }
//
// collision = getCollisionNormal(chunkManager, playerPos,
// zDirection,
// 'z');
// if (collision != null) {
// collisions.cross(collision);
// zCol = true;
// } else {
// zCol = false;
// }
} catch (OutsideOfWorldException e) {
e.printStackTrace();
}
return collisions;
}
/*
* Returns the normal of the colliding block, given the axis and
* direction.
*/
private static Vector3D getCollisionNormal(ChunkManager chunkManager,
Vector3D playerPos, float direction, char axis)
throws OutsideOfWorldException {
Block b;
Vector3D blockPos;
if (direction != 0) {
Vector3D dirVector;
if (axis == 'x') {
dirVector = new Vector3D(direction, 0, 0);
} else if (axis == 'y') {
dirVector = new Vector3D(0, direction, 0);
} else if (axis == 'z') {
dirVector = new Vector3D(0, 0, direction);
} else {
return null;
}
blockPos = playerPos.add(dirVector);
b = chunkManager.getBlock(blockPos);
if (b.isActive()) {
return Plane3D.getBlockNormal(blockPos, direction, axis);
}
}
return null;
}
private static float getCollisionDirection(float distance) {
if (distance > COLLISION_TOLERANCE) {
return 1;
} else if (distance < COLLISION_TOLERANCE) {
return -1;
}
return 0;
}
private static boolean isGrounded(Vector3D playerPosition,
ChunkManager chunkManager) {
try {
return chunkManager.getBlock(
playerPosition.add(new Vector3D(0, -1, 0))).isActive();
} catch (OutsideOfWorldException e) {
e.printStackTrace();
}
return true;
}
private static float getYOverlap(FPCameraController player,
ChunkManager chunkManager) {
Vector3D playerPosition = player.getPosition();
Vector3D blockPosition = player.getLowestBlockPos();
Block collisionBlock = null;
try {
collisionBlock = chunkManager.getBlock(blockPosition);
// +" "+blockPosition);
if (collisionBlock.isActive()) {
float distance = playerPosition.subtract(blockPosition).getY();
distance += player.getHeight();
return -distance;
}
} catch (OutsideOfWorldException e) {
e.printStackTrace();
}
return 0;
}
}
这是另一个相关方法:
public static Vector3D getBlockNormal(Vector3D blockPos, float direction,
char axis) {
float offset = Block.BLOCK_RENDER_SIZE / 2f;
Vector3D pointA = null;
Vector3D pointB = null;
Vector3D pointC = null;
Vector3D a = blockPos.round();
a = a.addScalar(Block.BLOCK_RENDER_SIZE / 2f);
float factor = -direction;
if (axis == 'x') {
pointA = a.add(new Vector3D(factor * offset, -offset, -offset));
pointB = a.add(new Vector3D(factor * offset, offset, -offset));
pointC = a.add(new Vector3D(factor * offset, -offset, offset));
} else if (axis == 'y') {
pointA = a.add(new Vector3D(-offset, factor * offset, offset));
pointB = a.add(new Vector3D(offset, factor * offset, offset));
pointC = a.add(new Vector3D(offset, factor * offset, -offset));
} else if (axis == 'z') {
pointA = a.add(new Vector3D(-offset, -offset, factor * offset));
pointB = a.add(new Vector3D(offset, -offset, factor * offset));
pointC = a.add(new Vector3D(offset, offset, factor * offset));
} else {
return null;
}
Vector3D v = new Vector3D(pointB.getX() - pointA.getX(), pointB.getY()
- pointA.getY(), pointB.getZ() - pointA.getZ()).normalize();
Vector3D w = new Vector3D(pointC.getX() - pointA.getX(), pointC.getY()
- pointA.getY(), pointC.getZ() - pointA.getZ()).normalize();
Vector3D normal = v.cross(w).scale(-1);
return normal.scale(factor);
}
最佳答案
如何处理碰撞是您的设计决定,选择您认为最自然的方式(详细说明如下):
最接近玩家位置的单个体素是您可以轻松导出更复杂方法的基础,只需使碰撞检测采用该体素进行检查即可。然后,您可以轻松扩展它以检查多个相邻的体素,为玩家提供您想要的大小。
例如,您可以将玩家视为圆柱体,并检查圆柱体覆盖的圆圈下方的所有体素。如果您检测到(例如)圆圈下方的单个熔岩体素,您可能会施加熔岩伤害(无论您的游戏使用什么地面属性)。
您需要尝试的另一个问题是海拔。您是否采用所覆盖体素的最高、最低或某种平均值来确定玩家当前所在的位置(或在飞行时与地面碰撞的高度)?
没有单一的方法可以让它“感觉良好”。您需要进行一些实验才能找到您认为对于游戏预期物理模型来说“自然”的东西。
如果您的物理允许快速移动,您可能需要扩展碰撞检查以检查两个游戏步骤之间对象覆盖的整个形状,以避免出现奇怪的现象,例如子弹穿过障碍物。因为从技术上讲,尽管它们的运动 vector 明显与障碍物相交,但它们的移动速度可能如此之快,以至于永远不会在障碍物内找到位置。
因此“将玩家坐标转换为体素空间”可以意味着任何内容,它没有详细定义方法。对于初始测试,您的“四舍五入到最近的 block ”可能已经足够好了,对于最终的游戏,您可能需要应用上面概述的一些概念来使其物理“感觉正确”。
关于java - 基本 3D 碰撞检测问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17281839/
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
我试图用这种形式简单地获取数字 28 integer+space+integer+integer+space+integer我试过这个正则表达式 \\s\\d\\d\\s 但我得到了两个数字11 和
最近一直在学习D语言。我一直对运行时感到困惑。 从我能收集到的关于它的信息中,(这不是很多)我知道它是一种有助于 D 的一些特性的运行时。像垃圾收集一样,它与您自己的程序一起运行。但是既然 D 是编译
想问一下这两个正则表达式有区别吗? \d\d\d 与 \d{3} 我已经在我的本地机器上使用 Java 和 Windows 操作系统对此进行了测试,两者都工作正常并且结果相同。但是,当在 linux
我正在学习 Go,而且我坚持使用 Go 之旅(exercise-stringer.go:https://tour.golang.org/methods/7)。 这是一些代码: type IPAddr
我在Java正则表达式中发现了一段令我困惑的代码: Pattern.compile( "J.*\\d[0-35-9]-\\d\\d-\\d\\d" ); 要编译的字符串是: String string
我在 ruby 代码上偶然发现了这个。我知道\d{4})\/(\d\d)\/(\d\d)\/(.*)/是什么意思,但是\1-\2-\3-\4 是什么意思? 最佳答案 \1-\2-\3-\4 是 b
我一直在努力解决这个问题,这让我很恼火。我了解 D 运行时库。它是什么,它做什么。我也明白你可以在没有它的情况下编译 D 应用程序。就像 XoMB 所做的那样。好吧,XoMB 定义了自己的运行时,但是
我有两个列表列表,子列表代表路径。我想找到所有路径。 List> pathList1 List> pathList2 当然是天真的解决方案: List> result = new ArrayList>
我需要使用 Regex 格式化一个字符串,该字符串包含数字、字母 a-z 和 A-Z,同时还包含破折号和空格。 从用户输入我有02-219 8 53 24 输出应该是022 198 53 24 我正在
目标是达到与this C++ example相同的效果: 避免创建临时文件。我曾尝试将 C++ 示例翻译为 D,但没有成功。我也尝试过不同的方法。 import std.datetime : benc
tl;dr:你好吗perfect forwarding在 D? 该链接有一个很好的解释,但例如,假设我有这个方法: void foo(T)(in int a, out int b, ref int c
有什么方法可以在 D 中使用abstract auto 函数吗? 如果我声明一个类如下: class MyClass { abstract auto foo(); } 我收到以下错误: mai
有没有人为内存中重叠的数组切片实现交集?算法在没有重叠时返回 []。 当 pretty-print (使用重叠缩进)内存中重叠的数组切片时,我想要这个。 最佳答案 如果您确定它们是数组,那么只需取 p
我已经开始学习 D,但我在使用 Andrei Alexandrescu 所著的 The D Programming Language 一书中提供的示例时遇到了一些麻烦。由于 int 和 ulong 类
如何创建一个不可变的类? 我的目标是创建一个实例始终不可变的类。现在我只是用不可变的方法和构造函数创建了一个“可变”类。我将其称为 mData,m 表示可变。然后我创建一个别名 alias immut
不久前我买了《The D Programming Language》。好书,很有教育意义。但是,我在尝试编译书中列出的语言功能时遇到了麻烦:扩展函数。 在这本书中,Andrei 写了任何可以像这样调用
我在 D http://www.digitalmars.com/d/2.0/lazy-evaluation.html 中找到了函数参数的惰性求值示例 我想知道如何在 D 中实现可能的无限数据结构,就像
这个问题在这里已经有了答案: 12 年前关闭。 Possible Duplicate: Could anyone explain these undefined behaviors (i = i++
当前是否可以跨模块扫描/查询/迭代具有某些属性的所有函数(或类)? 例如: source/packageA/something.d: @sillyWalk(10) void doSomething()
我是一名优秀的程序员,十分优秀!