当前位置: 首页 > 知识库问答 >
问题:

Slick2D矩形碰撞检测

巫欣荣
2023-03-14

我遇到了一个问题,显示一个矩形与另一个矩形发生了碰撞。所以我的问题是,如何让Intersect方法检查碰撞?或者在这种情况下有其他方法来处理碰撞吗?

我正在制作一个回合制战斗游戏(类似于《最终幻想》或《龙骑兵传说》),其中玩家的角色位于屏幕的右侧,敌人位于屏幕左侧。玩家和敌人轮流攻击。因此,当玩家攻击时,精灵动画会在屏幕上从右向左移动,直到它停在敌人面前,攻击并返回到其起始坐标。玩家和敌人都有一个围绕他们绘制的矩形,以表示每个角色的边界。

当玩家向前移动时,他穿过敌人的矩形并停在其中。此时,控制台的输出应该是“INTERSECT!”以表明两个矩形之间存在碰撞,但不幸的是没有。

请注意,我省略了类中不必要的代码片段,并尝试提供与我的问题相关的代码。

这是我的切入点,游戏类:

public class GameClass extends BasicGame{
//other variable declarations

public void init(GameContainer container) throws SlickException {
player = new Player();
enemy = new Enemy();
skeleton = new Skeleton();
enemy = skeleton;
playX = player.getStartX(); //700
playY = player.getStartY(); //140
playW = player.rect.getWidth(); //40
playH = player.rect.getHeight(); //70
enemyX = enemy.getStartX(); //100
enemyY = enemy.getStartY(); //140
enemyWidth = enemy.getWidth(); //50
enemyHeight = enemy.getHeight(); //55

SpriteSheet sheet = new SpriteSheet("data/homeranim.png", 36, 65);
    anim = new Animation();
    for (int i=0;i<8;i++) {
        anim.addFrame(sheet.getSprite(i,0), 150);
    }
}

public void render(GameContainer container, Graphics g)
        throws SlickException {
anim.draw(playX,playY); // draws player animation
skeletonAnim.draw(enemyX, enemyY); // draws enemy
g.draw(player.rect); //draws player bounds
g.draw(enemy.rect); //draws enemy bounds
}

public void update(GameContainer container, int delta)
        throws SlickException {
playerUpdate(delta);
if (player.rect.intersects(enemy.rect)) {
             System.out.println("INTERSECT!");

         System.out.println("Player minX: " + player.rect.getMinX());
         System.out.println("Player maxX: " + player.rect.getMaxX());
         System.out.println("Enemy minX: " + enemy.rect.getMinX());
         System.out.println("Enemy maxX: " + enemy.rect.getMaxX());
         }
      }

public void playerUpdate(int delta) {
    if (playerForward == true){
       playX -= delta * 0.4f;
       if (playX <= 140) {
             playX = 140;
             playerForward = false;
             playerBackward = true;}
  }

   if (playerBackward == true) {
         playX += delta * 0.4f;
         if (playX >= 700) {
             playX = 700;
             playerBackward = false;
             delay = 1250;
  }

public void keyReleased(int key, char c) {
       if (key == Input.KEY_ENTER){
          playerForward = true;}
}
}

以下是我的玩家类的一瞥:

public class Player {

private int startX = 700;
private int startY = 140;
public Shape rect = new Rectangle(startX, startY, 40, 70);
//plus getters and setters
}

还有我的整个敌人职业:

public class Enemy {

private int startX, startY, width, height;
public Shape rect = new Rectangle(startX, startY, width, height);
// plus getters and setters
   }

我的钢架雪车类扩展敌人:

public class Skeleton extends Enemy {

public Skeleton() {
    // TODO Auto-generated constructor stub
    setMaxHealth(120);
    setStartX(100);
    setStartY(140);
    setWidth(50);
    setHeight(55);
}

}

注意:因为我已经将g.drawRect()切换到g.draw(),所以没有画出敌人的矩形。

起点处的矩形边界:http://i.imgur.com/QDDk858.png

碰撞应该发生的地方:http://i.imgur.com/pOANfvN.png

我希望我已经提供了足够的代码来告诉你我的问题是什么。我已经在网上翻了几个小时了,运气不好。如果还有其他代码需要我提供,请不要犹豫,非常感谢你的帮助和支持!

共有1个答案

宗政深
2023-03-14

您没有更新自己的hitbox位置。

您正在绘制此:

g.drawRect(playX, playY, playW, playH); //draws player bounds
g.drawRect(enemyX, enemyY, enemyW, enemyH); //draws enemy bounds

但这不是真正的击中框,这只是玩家/敌人的位置,这里画的矩形会在正确的位置,而击中框本身不会。

我建议你这样做:

public void update(GameContainer container, int delta)
{
    playerUpdate(delta);

    player.rect.setLocation(playX, playY);
    enemy.rect.setLocation(enemyX, enemyY); // update the hitboxes to the new positions

    if (player.rect.intersects(enemy.rect))
    {
        System.out.println("INTERSECT!");
    }
}

public void playerUpdate(int delta)
{
    if (playerForward == true)
    {
       playX -= delta * 0.4f;

       if (playX <= 140) 
       {
             playX = 140;
             playerForward = false;
             playerBackward = true;
       }
    }

    if (playerBackward == true) 
    {
         playX += delta * 0.4f;

         if (playX >= 700) 
         {
             playX = 700;
             playerBackward = false;
             delay = 1250;
         }
    }
}

public void keyReleased(int key, char c) 
{
   if (key == Input.KEY_ENTER)
   {
      playerForward = true;
   }
}

此外,由于您似乎是Java游戏开发的新手,因此为您提供一些提示:

    < li >正确设置代码的格式

始终在如果,否则,切换,同时,为等之后放置完整的{...};正确的行缩进,.

这个很重要。你的敌人和玩家类都应该扩展某种实体类,因为他们都非常想获得相似的行为(避免代码重复!).将类似的行为归纳为一个超类,用几个可调参数简化要控制的行为等等。

例如,你将敌人和玩家的位置存储为主类中的静态整数。这不是OO。将位置移到实体类中,您可以在其中以任何方式实现它。

  • 不要无缘无故地抛出异常

您的 update(...) 方法会抛出一个光滑异常,即使它从不需要。

  • 封装时要小心

这是许多初学者都会做的事情:只需获取一些参数,将它们作为私有(甚至可能是公共)放在一个类中,然后为它们生成 getter 和 setters。这不是封装。这几乎和首先公开它们一样糟糕。

但是我们为什么不把一切都公之于众呢?

我们不希望任何人(甚至我们自己)依赖于某些参数,这些参数恰好存在,因为我们可能希望稍后更改某些非常具体的实现。不要只是将所有可能的值都放在那里进行更改,封装的意义在于独立于我们最终使用的实现类型,并通过保护可以设置/更改的内容来保护代码的可用性。

    < li >性能很重要

对于任何类型的软件来说,这都是你应该注意的一个方面,但是你经常可以在游戏中看到最明显的后果。性能很重要!我的意思并不是说您必须注意每一个细节,而是要记住如何改进和加速您的代码,特别是使用频繁调用的方法,比如update(..)和渲染(..)在Slick2D。

更新

作为评论中讨论的另一个问题的解决方案:

public class Enemy {

    private int startX, startY, width, height;
    public Shape rect = new Rectangle(startX, startY, width, height);
    // plus getters and setters
}

宽度和高度只能为 0,因为它们永远不会被分配一个整数,每个默认值的值为 0,因此敌人的矩形命中框的宽度为 0,永远不会触发。

尝试这样的事情:

 public class Enemy {

    private int startX, startY, width = 50, height = 70;
    public Shape rect = new Rectangle(startX, startY, width, height);
    // plus getters and setters
 }

这应该是可行的,但您可能应该将所有这些属性移到敌人的类中,并将它们放在构造函数中。

 类似资料:
  • 问题内容: 我遇到一个问题,即一个矩形与另一个矩形发生碰撞。所以我的问题是,如何获取相交方法以检查碰撞?还是在这种情况下还有其他方法可以处理碰撞? 我正在创建一个回合制战斗游戏(类似于《最终幻想》或《龙骑传奇》),其中玩家的角色在屏幕的右侧,而敌人在屏幕的左侧。玩家和敌人轮流进攻。因此,当玩家攻击时,子画面动画会从右到左在屏幕上移动,直到停在敌人面前,进行攻击并返回到其起始坐标。玩家和敌人周围都有

  • 问题内容: 问题: 我知道这个问题已经问了很多遍了,但是我没有找到任何好的答案。 所以我有一些游戏实体,现在检查碰撞的最佳方法是什么? 链接: 游戏(完成) 代码说明: 我有一个世界一流的实体列表: 我使用以下代码更新它们(仅在视图范围内): 所以现在我想检查实体更新方法中是否存在冲突。 我尝试将其作为更新方法: 这是当前的昆虫方法: 当前,相交方法始终返回true。但为什么? 问题答案: 实现此

  • 因此,我创建了一个方法来检测球形球和矩形球之间的碰撞。我把它分成了4部分;它检测圆的顶部、圆的左侧、圆的底部、圆的右侧和矩形之间的碰撞。其中的两个工作是检测圆上的左点和矩形之间的碰撞,以及检测圆上的右点和矩形之间的碰撞。但是,不起作用的是,如果最上面的点或最下面的点接触矩形,就不会检测到碰撞,正如我记录if语句以查看是否输入它时所看到的那样。下面是我的代码(方法。getr()获取圆圈半径): 我已

  • 我正在编写一个游戏,涉及碰撞的一个移动的圆,由用户控制,和一个移动的矩形,由计算机控制。 完整的代码可以在这里找到:游戏 我在圆和矩形之间的碰撞检测方面遇到了麻烦。当矩形是静态的,碰撞检测工作完美。当圆和矩形的边缘在任一边接触时,程序就会按照它应该的方式进行操作。 这是碰撞检测功能。 谢谢。

  • 在我的自上而下游戏中,当我的玩家通过婴儿床时,我该如何让他发生碰撞?我用的是交叉矩形。 这是我的密码 更新方法 在渲染方法中 这是完整的代码 谁能告诉我矩形碰撞检测的正确实现是什么?没有重叠,我是这个框架的新手。致谢和预付款:)

  • 所以我明白,我现在没有用最好的方式来编写这个代码;这是一种测试运行。我正在尝试使用矩形和intersects属性进行墙碰撞(抱歉,如果我没有使用正确的术语)。到目前为止,我有2个矩形在屏幕上。1玩家控制和游戏中与之冲突的其他玩家。当它们碰撞时,玩家停止移动。问题是,如果玩家试图移动到矩形,而他们已经碰撞,那么玩家不能在垂直于移动的任何方向移动,即如果玩家拿着右箭头键移动到矩形,那么他们不能向上或向