平台游戏的碰撞检测?

3
我一直在尝试弄清楚我的平台游戏是否有地图,我希望我的角色能够跳上一些平台。有没有简单的方法告诉游戏哪些平台可以跳上去并开始跳跃?
此外,像《超级马里奥兄弟》之类的游戏,它们的地图是用.txt文件制作的吗?因为我看了一个地图教程,他说所有专业的游戏开发者都会为地图制作一个.txt文件,并写下例如以下数字:
111111111111111111111
111111111111111111111
111111111111111111111
111111111111111111111
222222222222222222222
来创建地图。这正确吗?超级马里奥兄弟或洛克人游戏中的开发人员如何制作地图?
我想知道的是,如果我想让我的玩家能够跳上某些平台或其他东西,那该怎么办。

所有专业的游戏开发者都会为地图制作一个 .txt 文件并写入数字,这是完全不正确的。许多开发者使用各种地图编辑器,而这些地图的格式也各不相同。 - thedaian
但是如果我已经从地图编辑器中完成了一个地图,我该如何解决这个问题呢?例如,创建一个平台,并使得玩家跳跃时停留在该平台上而不是穿过它。 - User
@thedaian - 在2D游戏中,使用瓦片ID数字矩阵来表示地图是非常普遍的。显然,这不是手工完成的,而是由地图编辑器生成的。它也不是文本文档,因为那样会很慢。更可能的是二进制文件。 - MGZero
2个回答

2

一个非常简单的例子:

你可以通过一个数字矩阵来表示地图。数字1代表障碍物,数字0代表开放空间。

                   [000000]              [      ]
int[] map    ==    [000000]      ==      [      ]
                   [000111]              [   xxx]
                   [001111]              [  xxxx]

玩家对象还必须在矩阵内具有坐标,其中水平位置(X)是列,垂直位置(Y)是行,并且具有速度(方向和速度)。速度由用户输入控制,例如按右箭头将将X方向设置为速度+1。

int xPos;
int yPos

int xSpeed;
int ySpeed;

while(true) {
    // Check user input
    if (upArrow()) {
        ySpeed = 1;
    }
    if (downArrow()) {
        ySpeed = -1;
    }
    if (leftArrow()) {
        ySpeed = -1;
    }
    if (rightArrow()) {
        ySpeed = 1;
    }

    // Update player position
    xPos = xPos + xSpeed;
    yPos = yPos + ySpeed;

// ...

现在您只需检查玩家对象在矩阵中的当前位置的数字。如果是0,则不做任何操作;如果是1,则将速度设置为0。请保留HTML标签。
    int mapObstacle = map[xPos, yPos];
    if (mapObstacle == 1) {
        // Stop player movement
        xSpeed = 0;
        ySpeed = 0;
    }
}

为了将地图保存在txt文件中,您必须让游戏从文件中读取/写入地图矩阵。以下是读取的示例。

int n = 0;
while (mapFile.hasNextLine()) {
    String mapLine = mapFile.nextLine();

    for (int i = 0, n = mapLine.length; i < n; i++) {
        int mapObstacle = Integer.parseInt(mapLine.charAt(i));
        map[n, i] = mapObstacle; // Read map layout
    }
    n++;
}

但是如果我已经从地图编辑器中完成了一个地图,我该如何解决这个问题呢?例如,创建一个平台,并使得玩家跳跃时停留在该平台上而不是穿过它。 - User
它涉及一些进一步的机制,您需要检查地图矩阵中的障碍物,并像我上面描述的那样改变玩家的速度。我建议您先创建游戏“贪吃蛇”,以掌握使用矩阵和速度的技巧。当您完成贪吃蛇后,您将了解如何创建平台游戏。 - Felix Glas

0

使用文本文件是可以的,但使用PNG或位图图形更好。一个像素可以潜在地存储多达4个字节的信息,并且可以使用照片处理工具轻松创建。

首先,在所有之前,您应该拥有一个“实体”或“游戏对象”类,使您场景中的所有内容都可以继承。例如:

public class Entity
{
    public float x, y, width, height;

    public void onStep() {}
    public void onDraw() {}

    public RectF getRectF()
    {
        RectF rect = new RectF();
        rect.left = x;
        rect.top = y;
        rect.right = x + width;
        rect.bottom = y + height;
        return rect;
    }
}

其次,您应该拥有一些不同的类来扩展实体类,例如Player类、Wall类,以及可能的Coin类:

public class Player extends Entity {...}
public class Wall extends Entity {...}
public class Coin extends Entity {...}

你的下一步是覆盖Player的step事件,并在该step事件中像以下方式一样迭代所有的墙实体:

@Override public void onStep()
{
    for (Entity e : my_active_entities)
    {
        if (e instanceof Wall)
        {
            Wall wall = (Wall) e;

            if (RectF.intersects(wall.getRectF(), this.getRectF()))
            {
                // We now know that our player is intersecting with "e"
                // We also know that "e" is a wall

                wall.doSomething();
                this.doSomething();
            }
        }
    }
}

最后,是创建自己的舞台加载器。这将遍历您的图形和绘图对象,并根据当前像素的颜色在屏幕上绘制它们。
Bitmap bitmap = getOurBitmapFromSomewhere();

for (int x = 0; x < bitmap.getWidth(); x++)
    for (int y = 0; y < bitmap.getHeight(); y++)
    {
        int color = bitmap.getPixel(x, y);

        switch (color)
        {
            case 0xFF00FF00:
                // First byte is Alpha
                // Second byte is Red
                // Third byte is Green
                // Fourth byte is Blue

                Player player = new Player();
                player.x = x * TILE_SIZE; // For example, 16 or 32
                player.y = y * TILE_SIZE;

                my_active_entities.add(player);
                break;
        }
    }

这就是我关于游戏对象处理、碰撞检测和关卡加载的一些经验分享。任何偶然看到这篇文章的人都可以在他们的软件中使用这段代码或者这个代码概念。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接