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

Java游戏中的2D碰撞问题

冯开诚
2023-03-14

我已经和LWJGL一起开发这个游戏几个星期了。自从我增加了跳跃的能力后,向上的碰撞给我带来了很多问题。

这个游戏是一个基于2D瓷砖的侧翻游戏。总的来说,除了玩家跳跃时,碰撞几乎是完美的。起初我想“哦,也许我只需要改变跳跃机制”,但后来我意识到只有当玩家通过某个x坐标时才会发生这种情况。

现在,对于实际问题本身:如果玩家在传递某个x坐标时跳转,他们将通过平铺,并测试顶部碰撞返回false。

这是整个玩家类:

package Minecraft2D;

import static Minecraft2D.World.BLOCK_SIZE;
import Minecraft2D.Tools.Tools;
import Minecraft2D.UI.Inventory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import static Minecraft2D.Boot.*;

import org.lwjgl.util.Rectangle;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;

public class Player {

private float x;
private float y;
public int width = 32;
public int height = 50;
private float DX = 0;
private float DY = 0;
private Texture left = null;
private Texture right = null;
Texture texture = null;

public boolean direction[] = { false, false, false, false };
public boolean collision = false;
public boolean ground = false;
public boolean jump = false;
public boolean top = false;

public Player(float x, float y) {
    this.x = x;
    this.y = y;
    try {

        this.left = TextureLoader.getTexture("PNG", new FileInputStream(new File(path + "player_left.png")));
        this.right = TextureLoader.getTexture("PNG", new FileInputStream(new File(path + "player_right.png")));
        this.texture = this.right;
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void draw() {
    Tools.drawTexture((int)x, (int)y, width, height, texture);
}

public void checkCollision(Player player, Block block) {

    if (player.getY() < block.getY() + BLOCK_SIZE && player.getX() < block.getX() + BLOCK_SIZE && player.getY() + this.height > block.getY() && player.getX() + this.width > block.getX() && block.getType() != BlockType.AIR) {
        Rectangle top = new Rectangle();
        top.setBounds((int) player.x + 4, (int) player.y + 1, this.width - 8, 1);
        Rectangle bottom = new Rectangle();
        bottom.setBounds((int) player.x + 4, (int) player.y + this.height, this.width - 8, 1);
        Rectangle left = new Rectangle();
        left.setBounds((int) player.x, (int) player.y + 1, 1, this.height - 5);
        Rectangle right = new Rectangle();
        right.setBounds((int) player.x + player.width, (int) player.y + 1, 1, this.height - 5);
        Rectangle blok = new Rectangle();
        blok.setBounds((int) block.getX(), (int) block.getY(), BLOCK_SIZE, BLOCK_SIZE);
        if (bottom.intersects(blok)) {
            player.setY((block.getY() - this.height - 1));
            ground = true;
            jump = false;
        } else if (top.intersects(blok)) {
            DY = 0;
            this.top = true;
            y -= (player.y) - (block.getY() + BLOCK_SIZE);
        }
        if (!top.intersects(blok)) {
            if (left.intersects(blok)) {
                player.setX(block.getX() + this.width);
            } else if (right.intersects(blok)) {
                player.setX(block.getX() - this.width);
            }
        }

    } else {
        collision = false;
        ground = false;
    }


    if (!collision && !jump) {
        setDY(.003f);
    }
    if (ground && !jump) {
        DY = 0;
    }

    if (jump && DY < 0.003f) {
        DY += 0.0001;
    } else {
        // jump = false;
    }

    if (top) {
        DY = 0f;
        top = false;
    }

    x += DX;
    y += DY;

    if (x > Boot.SCREEN_WIDTH) {
        x = 0;
    }
    if (x < 0) {
        x = Boot.SCREEN_WIDTH;
    }
}

public float getX() {
    return x;
}

public void setX(float x) {
    this.x = x;
}

public float getY() {
    return y;
}

public void setY(float y) {
    this.y = y;
}

public void setDX(float dx) {
    this.DX = dx;
}

public void setDY(float dy) {
    this.DY = dy;
}

public void setJump() {
    if (!jump) {
        jump = true;
        ground = false;
        DY = -0.13f;
        y -= 1;
    }
}

public void setTexture(int tex) {
    if (tex == 0) {
        this.texture = this.left;
    }
    if (tex == 1) {
        this.texture = this.right;
    }
}

}

==============

编辑:我不知道为什么,但当我的角色靠近贴图的0 x坐标时,角色的y坐标会缓慢增加。这可能与我遇到的问题有关。我正在研究这个问题,我怀疑当我将玩家的x和y值从双精度转换为整数,用于顶部、底部、左侧和右侧矩形时,可能会有一些问题。

再次编辑:我不知道这是否重要,但我一直在像这样检查碰撞:(这是在“引导”类中。)

private void checkCollision() {
            for (int x = 0; x < BLOCKS_WIDTH - 1; x++) {
              for (int y = 0; y < BLOCKS_HEIGHT - 1; y++) {
                Block blk = grid.getAt(x, y);
                player.checkCollision(blk);
            }
        }
}

共有1个答案

井翰
2023-03-14

你为什么要把一个玩家传入checkCollision?看起来你不应该传入一个玩家,而是使用调用checkCollision方法的玩家成员。我认为这可能会给你带来一些困惑。例如:

y -= (player.y) - (block.getY() + BLOCK_SIZE);

这看起来就像你试图将玩家推到他们在跳跃期间与之相交的块b / c下方。如果是这样的话,它应该只是

y = (block.getY() + BLOCK_SIZE);

我会从函数参数中删除播放器并重写函数,看看你会得到什么。希望这有帮助。

编辑

您的评论声明您不能再将播放器传递到函数中。我不确定你的具体实现,但是我通常看到的游戏是这样的:

 public class Player 
 {
    private int x, y, dx, dy;

    public void checkCollision(Block block)
    {
       if (isTopCollision(block))
         fall(block.getY() + block.getHeight());
    }

    private boolean isTopCollision(Block block)
    {
       return y > block.getY() + block.getSize() && y < block.getY();
    }

    private void fall(int adjustedY)
    {
       y = adjustedY;
       top = true;
       dy = 0;
       // etc
    }
 }

 public class MyGame 
 {
     public void gameloop()
     {
       for (Block b : blocks)
         player.checkCollision(b);
     }
 }
 类似资料:
  • 我正在尝试制作我的第一个Pacman游戏,但我遇到了一堵我自己似乎无法打破的墙:( 这是关于如何在我的游戏中检测碰撞,所以步行者不能穿过障碍物/墙壁。我已经使它不能去屏幕外与此代码: ,但如果我在屏幕中间的电路板上有一个矩形,我不知道如何编程,这样它就会在墙前停止。 我需要阻止我的pacman移动到竞技场内的墙上,如你所见(左上方的矩形) 我的Board类代码: 希望有人能告诉我该怎么做...似乎

  • 我对libgdx和游戏开发非常陌生。我的任务是给我一个非常简单的2D游戏,它已经实现了矩形碰撞检测。 游戏只是由一个可以由玩家控制的正方形组成,该正方形位于墙壁内,墙壁内有其他分散的正方形。我现在需要在玩家方块和散落方块/墙壁之间实现像素完美碰撞。 我最初尝试使用Pixmap,并试图检查当前坐标的像素对于播放器矩形以及与之冲突的任何矩形是否透明,但在正确实现代码时遇到了问题。 我知道我必须在某个坐

  • 我已经尝试了好几天,花了几个小时在网上搜索,但无济于事。我在碰撞时遇到问题,我可以检测到碰撞,但我的问题是阻止玩家进入图块。我已经尝试了所有我能想到的。我正在检测我的瓷砖贴图的冲突,使用1表示实体,0表示被动 这工作正常,我的文本播放器变成红色,一旦与瓷砖碰撞,但我不知道如何防止玩家进入那个瓷砖开始,我目前的设置我试图禁用移动,但所有发生的是玩家进入碰撞设置为true和控件禁用,导致玩家完全卡住。

  • 我正在尝试用SFML 2.1为我的2D超级马里奥兄弟克隆包碰撞。我尝试了很多不同的解决方案和想法,但我无法让任何东西正常工作。 我有一个播放器,它目前在自己的更新()中检查碰撞(如下所示) 当前: 1. 我的碰撞检测到碰撞略微偏移。如果你能找到任何明显的错误,我会很高兴知道。 2.我不确定这是否是一个足够好的解决方案,因为我需要检测4个方向的碰撞(跳跃,撞到我的头块。摔倒在方块上,左右碰撞) 3.

  • 我想创建一个二维游戏与瓷砖为基础的地图。我的主要问题是碰撞。如果有一棵树挡住了我的路,我怎么才能让我的精灵不穿过这棵树呢?

  • 所以我正在android studio中制作一款突破性游戏。 在做了一个游戏循环和与桨和桨的基本碰撞后,我注意到我的球在提高速度后开始穿过我的桨和桨。 问题在于它在一帧中碰撞了两次,所以我的基本碰撞还不够。 我读过关于使用向量数学求解的书。但这对我来说太过分了,我的头也被它缠住了。我指的是这个问题的答案: