Определить, на какой куб смотрит пользователь? - PullRequest
0 голосов
/ 22 февраля 2019

Я делаю игру вроде Minecraft, используя python.У меня есть мир, в котором пользователь может ходить и смотреть по сторонам, но я не знаю, как сделать так, чтобы они могли разбивать и размещать блоки.

Мне нужно знать, как рассчитать блок, которым он являетсяглядя на трехмерный массив блоков в мире (blocks, формат: [[[a,b,c],[d,e,f],[g,h,i]],[[j,k,l],[m,n,o],[p,q,r]],[[s,t,u],[v,w,x],[y,z,0]]]), их положение (x, y, z) и вращение головы (xrot, yrot)).

Мне также нужно это только на определенном расстоянии от того места, где они находятся, может быть, 5 блоков.Я попытался найти функцию для линии и отчасти следовать ей, но это не сработало, и я осмотрелся в Интернете и не смог найти то, что мне нужно.

Мне нужно иметь возможностьвыяснить, какой блок они сломают или куда пойдет новый блок, основываясь на стороне, на которую они смотрят.

Мне не нужно знать, как перебирать трехмерную сетку, и мне не нужно, чтобы это былотолько один раз для каждого куба мне нужно выяснить, на какой блок они смотрят и на какое лицо смотрят.Я сделал этот код, используя свои математические знания, но по какой-то причине он просто не работает как 80% времени, но иногда он может определить, на какой куб я смотрю (Обратите внимание, 0,0,0 кубав центре внизу)

def get_looking_at(xrot, yrot, xpos, ypos, zpos, blocks, reach):
    xrot, yrot = math.radians(xrot), math.radians(yrot)
    xform = sin(xrot)*cos(yrot)+xpos
    yform = sin(yrot)+ypos
    zform = -(cos(xrot)*cos(yrot))+zpos
    xforward = xform-xpos >= 0
    yforward = yform-ypos >= 0
    zforward = zform-zpos >= 0
    if xforward:
        xset = [floor(x+xpos+.5)+.5 for x in range(reach)]
    else:
        xset = [floor((-x)+xpos+.5)-.5 for x in range(reach)]
    if yforward:
        yset = [ceil(y+ypos) for y in range(reach)]
    else:
        yset = [floor((-y)+ypos) for y in range(reach)]
    if zforward:
        zset = [floor(z+zpos+.5)+.5 for z in range(reach)]
    else:
        zset = [floor((-x)+xpos+.5)-.5 for x in range(reach)]
    xint = []
    yint = []
    zint = []
    for x in xset:
        y = ((yform-ypos)*x)/(xform-xpos)
        z = ((zform-zpos)*x)/(xform-xpos)
        xint.append((x, y+ypos, z+zpos))
    for y in yset:
        x = ((xform-xpos)*y)/(yform-ypos)
        z = ((zform-zpos)*y)/(yform-ypos)
        yint.append((x+xpos, y, z+zpos))
    for z in zset:
        x = ((xform-xpos)*z)/(zform-zpos)
        y = ((yform-ypos)*z)/(zform-zpos)
        zint.append((x+xpos,y+ypos,z))
    intercepts = dict()
    for pos in xint:
        intercepts[(pos[0]-xpos)**2+(pos[1]-ypos)**2+(pos[2]-zpos)**2] = (pos[0], pos[1], pos[2], "x")
    for pos in yint:
        intercepts[(pos[0]-xpos)**2+(pos[1]-ypos)**2+(pos[2]-zpos)**2] = (pos[0], pos[1], pos[2], "y")
    for pos in zint:
        intercepts[(pos[0]-xpos)**2+(pos[1]-ypos)**2+(pos[2]-zpos)**2] = (pos[0], pos[1], pos[2], "z")
    indices = [x for x in intercepts]
    indices.sort()
    for index in indices:
        connection = intercepts[index]
        if xforward:
            x = floor(connection[0]+.5)
            xdir = "e"
        else:
            x = ceil(connection[0]-.5)
            xdir = "w"
        if yforward:
            y = floor(connection[1])
            ydir = "d"
        else:
            y = floor(connection[1])+1
            ydir = "u"
        if zforward:
            z = ceil(connection[2]-.5)
            zdir = "n"
        else:
            z = floor(connection[2]+.5)
            zdir = "s"
        print(x,y,z)
        try:
            if blocks.get_data(x, y, z) != None:
                if math.sqrt(index) <= reach:
                    if connection[3] == "x":
                        return x, y, z, xdir
                    if connection[3] == "y":
                        return x, y, z, ydir
                    if connection[3] == "z":
                        return x, y, z, zdir
                else:
                    return
            else:
                continue
        except IndexError:
            continue
    return

1 Ответ

0 голосов
/ 02 марта 2019

Вы можете создать сферу контакта вокруг игрока и использовать радиус, «выступающий» от лица игрока.

Радиус r будет максимальным расстоянием, на которое пользователь мог бы смотреть на блок и при этом иметь возможностьповлиять на него.

Используя треугольники, вы можете определить, находится ли конец радиуса внутри блока или нет, и т. д.

...