我一直在尝试使用碰撞检测来阻止物体相互碰撞。但我不知道怎么做。
当物体碰撞时,我试着颠倒它们速度矢量的方向(所以它远离碰撞的地方),但是有时物体会卡在对方体内。
我试着改变他们的速度,但这只是父母彼此的反对。
有没有一种简单的方法来限制物体的运动,这样它们就不会穿过其他物体?我一直在使用矩形相交来进行碰撞,我还尝试了圆形冲突检测(使用对象之间的距离)。
思想?
package objects;
import java.awt.Rectangle;
import custom.utils.Vector;
import sprites.Picture;
import render.Window;
// Super class (game objects)
public class Entity implements GameObject{
private Picture self;
protected Vector position;
protected Vector velocity = new Vector(0,0);
private GameObject[] obj_list = new GameObject[0];
private boolean init = false;
// Takes in a "sprite"
public Entity(Picture i){
self = i;
position = new Vector(i.getXY()[0],i.getXY()[1]);
ObjectUpdater.addObject(this);
}
public Object getIdentity() {
return this;
}
// position handles
public Vector getPosition(){
return position;
}
public void setPosition(double x,double y){
position.setValues(x,y);
self.setXY(position);
}
public void setPosition(){
position.setValues((int)Window.getWinSize()[0]/2,(int)Window.getWinSize()[1]/2);
}
// velocity handles
public void setVelocity(double x,double y){ // Use if you're too lazy to make a vector
velocity.setValues(x, y);
}
public void setVelocity(Vector xy){ // Use if your already have a vector
velocity.setValues(xy.getValues()[0], xy.getValues()[1]);
}
public Vector getVelocity(){
return velocity;
}
// inferface for all game objects (so they all update at the same time)
public boolean checkInit(){
return init;
}
public Rectangle getBounds() {
double[] corner = position.getValues(); // Get the corner for the bounds
int[] size = self.getImageSize(); // Get the size of the image
return new Rectangle((int)Math.round(corner[0]),(int)Math.round(corner[1]),size[0],size[1]); // Make the bound
}
// I check for collisions where, this grabs all the objects and checks for collisions on each.
private void checkCollision(){
if (obj_list.length > 0){
for (GameObject i: obj_list){
if (getBounds().intersects(i.getBounds()) && i != this){
// What happens here?
}
}
}
}
public void updateSelf(){
checkCollision();
position = position.add(velocity);
setPosition(position.getValues()[0],position.getValues()[1]);
init = true;
}
public void pollObjects(GameObject[] o){
obj_list = o;
}
}
希望它不太难阅读。
编辑:所以我一直在使用矩形交叉方法来计算物体的位置和修改速度。它工作得很好。唯一的问题是有些物体推动其他物体,但这很重要。碰撞对我正在创作的迷你游戏来说几乎是一件额外的事情。谢谢你的帮助。
尽管如此,我仍然非常感谢对所提到的想法的详细阐述,因为我不完全确定如何将它们实施到我的项目中。
没有看到你的代码,我只能猜测发生了什么。我怀疑你的对象被卡住了,因为它们超出了其他对象的边界,最终进入了内部。确保每个物体的步长不仅仅是速度*delta_time,而是步长受到潜在碰撞的限制。当发生碰撞时,计算它发生的时间(在delta_time的某个地方),并跟随反弹来确定最终的物体位置。或者,只需将物体设置为触摸,速度根据动量守恒定律改变。
在看到你的代码后编辑,我可以扩展我的答案。首先,让我澄清一下你提到的一些术语。由于每次调用updateSelf
都只是将速度向量添加到当前位置,因此实际上是一个单位时间增量(增量时间始终为1)。换句话说,您的“速度”实际上是自上次调用updateSelf
以来经过的距离(速度*增量时间)。我建议在模拟中使用显式(浮动)时间增量。
其次,跟踪多个运动物体之间碰撞的一般问题非常困难。无论使用什么时间增量,对象都有可能在该增量中经历多次碰撞。(想象一个物体被挤压在另外两个物体之间。在任何给定的时间间隔内,物体在两个周围物体之间来回弹跳的次数没有限制。)此外,一个对象可能(在计算分辨率范围内)同时与多个对象碰撞。如果对象在移动时实际改变大小(正如代码所示),问题就更复杂了。
第三,您有一个重要的误差源,因为您将所有对象位置舍入为整数坐标。我建议用浮点对象来表示你的对象(矩形2D. Float
而不是矩形
;Point2D. Float
而不是Vector
)。我还建议将位置字段替换为矩形边界字段,该字段可以捕获位置和大小。这样,您就不必在每次调用getBound()
时创建新对象。如果对象大小不变,这也将简化边界更新。
最后,在每个对象内部都有一个重要的冲突检测逻辑问题:当对象a发现它会撞到对象B时,对象B也会撞到对象a!但是,对象B独立于对象A进行自己的计算。如果先更新A,则B可能会错过碰撞,反之亦然。最好将整个碰撞检测和对象移动逻辑移动到一个全局算法,并保持每个游戏对象相对简单。
一种方法(我推荐)是编写一个“updateGame”方法,以给定的时间增量推进游戏状态。它将使用一个记录碰撞的辅助数据结构,可能如下所示:
public class Collision {
public int objectIndex1; // index of first object involved in collision
public int objectIndex2; // index of second object
public int directionCode; // encoding of the direction of the collision
public float time; // time of collision
}
整体算法将游戏从当前时间推进到由参数deltaTime
定义的新时间。它的结构可能是这样的:
void updateGame(float deltaTime) {
float step = deltaTime;
do (
Collision hit = findFirstCollision(step);
if (hit != null) {
step = Math.max(hit.time, MIN_STEP);
updateObjects(step);
updateVelocities(hit);
} else {
updateObjects(step);
}
deltaTime -= step;
step = deltaTime;
} while (deltaTime > 0);
}
/**
* Finds the earliest collision that occurs within the given time
* interval. It uses the current position and velocity of the objects
* at the start of the interval. If no collisions occur, returns null.
*/
Collision findFirstCollision(float deltaTime) {
Collision result = null;
for (int i = 0; i < obj_list.length; ++i) {
for (int j = i + 1; j < obj_list.length; ++j) {
Collision hit = findCollision(i, j, deltaTime);
if (hit != null) {
if (result == null || hit.time < result.time) {
result = hit;
}
}
}
}
return result;
}
/**
* Calculate if there is a collision between obj_list[i1] and
* obj_list[i2] within deltaTime, given their current positions
* and velocities. If there is, return a new Collision object
* that records i1, i2, the direction of the hit, and the time
* at which the objects collide. Otherwise, return null.
*/
Collision findCollision(int i1, int i2, float deltaTime) {
// left as an exercise for the reader
}
/**
* Move every object by its velocity * step
*/
void updateObjects(float step) {
for (GameObject obj : obj_list) {
Point2D.Float pos = obj.getPosition();
Point2D.Float velocity = obj.getVelocity();
obj.setPosition(
pos.getX() + step * velocity.getX(),
pos.getY() + step * velocity.getY()
);
}
}
/**
* Update the velocities of the two objects involved in a
* collision. Note that this does not always reverse velocities
* along the direction of collision (one object might be hit
* from behind by a faster object). The algorithm should assume
* that the objects are at the exact position of the collision
* and just update the velocities.
*/
void updateVelocities(Collision collision) {
// TODO - implement some physics simulation
}
MIN_STEP
常量是一个最小的时间增量,以确保游戏更新循环不会因为更新如此小的时间步长而无法取得进展。(使用浮点时,deltaTime-=step;
可能保持deltaTime
不变。)
关于物理模拟:维基百科上关于弹性碰撞的文章为这个问题提供了一些很好的数学。
碰撞检测 现在你知道了如何制造种类繁多的图形对象,但是你能用他们做什么?一个有趣的事情是利用它制作一个简单的 碰撞检测系统 。你可以用一个叫做:hitTestRectangle 的自定义的函数来检测两个矩形精灵是否接触。 hitTestRectangle(spriteOne, spriteTwo) 如果它们重叠, hitTestRectangle 会返回 true。你可以用 hitTestRect
本节暂未进行完全的重写,错误可能会很多。如果可能的话,请对照原文进行阅读。如果有报告本节的错误,将会延迟至重写之后进行处理。 当试图判断两个物体之间是否有碰撞发生时,我们通常不使用物体本身的数据,因为这些物体常常会很复杂,这将导致碰撞检测变得很复杂。正因这一点,使用重叠在物体上的更简单的外形(通常有较简单明确的数学定义)来进行碰撞检测成为常用的方法。我们基于这些简单的外形来检测碰撞,这样代码会变得
我正在为HS的最后一年项目开发一个平台游戏。然而…我使用的冲突检测系统基本上是关于检查阉羊角色的特定部分是否与另一个块相交。 碰撞似乎工作得很好,除了它会导致一些错误,例如玩家在从侧面撞击时卡住或减速,或者在上边和下边都被抛起时被抛起 我的问题是;我如何改进碰撞代码,以避免这种小故障,并有一种'滑'碰撞? 这是边界的预览 以下是绑定方法: 编辑:Im使用恒定的加速度来设置速度
问题内容: 有人可以帮我了解JS中冲突检测的工作原理吗?我不能使用jQuery或gameQuery-已经使用了原型- 因此,我正在寻找非常简单的东西。不要求完整的解决方案,只需为我指明正确的方向。 假设有: 现在球正在移动(任何方向)。“ Someobject”(0-X)已经预先定义,其中有20-60个随机放置,如下所示: 我可以创建一个位置为“ someobject(X)”的数组,并在“球”移动
我已经尝试添加冲突检测一段时间了,但似乎做不到... 要绘制地图,我只需使用x,y坐标: 使用这种方法,我想出了这种检测: 我一直在尝试使用for循环遍历树来检测玩家(一个矩形)是否穿过树,但我想不出任何东西。 我已经试过了 如果碰撞=true,player.update(碰撞)将矩形更改为红色,如果为false,将矩形变为黑色。 我已尝试使用for和if,例如: 等但这不起作用,它只适用于wit
所以我试图用Python和Pyplay创建一个益智平台游戏,但是我遇到了一点麻烦。当我为主要角色使用单点图像,而不是矩形图像时,如何制作碰撞检测器?我知道直角图像有左、右、顶部和底部像素功能(这对冲突检测非常有用),但是对于单片图像有这样的功能吗?或者我只需要为x和y坐标创建一个变量图像的宽度/高度?我试过用那个 但是catImg一直在通过窗户的尽头。我做错了什么?提前谢谢。