0

我一直在努力解决如何在我正在编写的游戏中实现简单的方形碰撞检测,同时避免使用 Pygame;我想学习如何在不作弊的情况下做到这一点。预期的程序结构如下: 游戏加载一个包含关卡的文本文件。每个级别由 25 行 25 位数字组成(总共 625 位数字)。它被提取到二维数组中以模拟与屏幕对应的笛卡尔网格。从那里程序在屏幕上的适当位置绘制一个 32x32 块。例如,如果位置 [2][5] 处的数字是 1,它将在像素坐标 (96,192) 处绘制一个白色正方形(正方形的计数从零开始,因为它是一个数组)。它还为与原始数组对应的每个位置生成一个由 True 或 False 组成的碰撞数组。

我有一个沿网格自由移动的玩家对象,不限于 32x32 方格。我的问题是:我将如何实现方形碰撞检测?我已经尝试了很多方法,但我不太确定我在哪里卡住了。我将在下面发布我的最新版本和相关代码。

碰撞代码:

def checkPlayerEnvCollision(self,player):
    p = player
    c = self.cLayer #this is the collision grid generated when loading the level
    for row in range(25):
        for col in range (25):
            print("checkEnvCollision")
            if c[row][col] != False:
                tileleftx = row*32
                tilerightx = tileleftx + 32
                tilelefty = col*32
                tilerighty = tilelefty+32
                if (abs(tileleftx - p.x) * 2 < (tilerightx + (p.x + 32))) and (abs(tilelefty - p.y) * 2 < (tilerighty + (p.y + 32))):
                    print("OH NO, COLLISION")

将文本文件中的图块加载到数组中的代码:

def loadLevel(self, level):
    print("Loading Level")
    levelFile = open(level)
    count=0
    for line in levelFile:
        tempArray = []
        if line.startswith("|"):
            dirs = line.split('|')
            self.north = dirs[1]
            self.south = dirs[2]
            self.east = dirs[3]
            self.west = dirs[4]
            continue

        for item in line:
            if item in self.tileValues:
                tempArray.append(int(item))
        self.tileLayer[count] = tempArray
        count+=1
    for items in self.tileLayer:
        if len(items) > 25:
            print("Error: Loaded Level Too Large")

    count = 0
    for line in self.tileLayer:
        tempArray = []
        for item in line:
            if self.tilePassableValues[item] == False:
                tempArray.append(False)
            else:
                tempArray.append(True)
        self.collisionLayer[count] = tempArray
        count += 1

不确定这是否有用,但这里是绘图方法的简单演示:

def levelTiles(self, level):
    row = 0
    for t in level:
        col = 0
        for r in t:
            color = "white"
            if r == 0:
                col+=1
                continue
            elif r == 1:
                color = "red"
            elif r == 2:
                color = "white"
            elif r == 3:
                color = "green"
            self.Canvas.create_rectangle(row*32, col*32, row*32+32, col*32+32, fill=color, width=1,tags='block')
            col += 1
        row += 1

最后,这是我一直在测试的文本文件:

1111111111111111111111111
1222222222222222222222221
1222222222222222222222221
1222222222222222222222221
1222222222222222222222221
1222222222222222222222221
1222233332222222222222221
1222233332222222222222221
1222222222222222222222221
1222222222222222222222221
1222222222222222222222221
1222222222222222222222221
1222222222222222222222221
1222222222233332222222221
1222222222333332332222221
1222222222222222332222221
1222222222222222332222221
1222222222222222222222221
1222222222222222222222221
1222222222222222222222221
1222222222222222222222221
1222222222222222222222221
1222222222222222222222221
1222222222222222222222221
1111111111111111111111111
|onescreen2|onescreen2|onescreen2|onescreen2

(最后一行是到达关卡边缘时将地图加载到北、南、东和西的内容;您可以忽略它。)

谢谢您的帮助。有很多问题要问,但我坚持这个!

4

2 回答 2

0

如果玩家被绑在网格上,为什么不测试网格位置:

if grid[player.x][player.y] == some_collidable_thing:
    # there was a collision

如果没有,
我还在这个问题中提供了几乎相同的答案

def check_col(self, rect):
    for row in self.cLayer:
        for column in row:
            grid_position = (row*element_size, column*element_width)
            collide_x = False
            collide_y = False

            # check x axis for collision
            if self.rect.x + self.rect.w > grid_position[0]:
                collide_x = True
            elif self.rect.x < grid_position[0] + element_width:
                collide_x = True

            # check y axis for collision
            if self.rect.y < grid_position[1] + element_height:
                collide_y = True
            elif self.rect.y + self.rect.h > grid_position[1]:
                collide_y = True

            # act on a collision on both axis
            if collide_x and collide_y:
                # act on the collision
                return True
            else:
                # act on no collision
                return False
于 2013-04-10T00:50:40.327 回答
0

一个更简单的方法是为玩家的运动定义向量,为对象的边界定义线条。然后检查向量是否与任何线碰撞(不应该检查很多线)如下(我假设玩家/对象可以在另一个对象的边界上):

取由运动矢量和要检查碰撞的线的端点形成的三角形的行列式,并通过行列式取其面积。将其面积与另一个端点形成的三角形面积进行比较。如果它们都是正/负,则没有交集。如果他们的标志不同,那么可能会有一个交叉点。

如果它们的符号不同,则执行与上述相同的操作,只是使用运动矢量的端点而不是直线的端点。(并使用整条线而不是运动矢量)。

如果它们的符号不同,那么肯定有一个交叉点,如果它们相同,那么就没有交叉点。

我希望这会有所帮助(如果没有意义,请发表评论)。

于 2013-04-10T02:27:42.687 回答