1

I am making game sort of like Minecraft using python. I have a world that the user can walk around and look around in but I don't know how to make it so they can break and place blocks.

I need to know how to calculate the block that they are looking at from a 3d array of the blocks in the world (blocks, format:[[[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]]]), their position (x,y,z) and head rotation (xrot,yrot).

I also only need it in a certain distance away from where they are, maybe 5 blocks. I tried to find a function for a line and kind of follow it but that didn't work out and I looked around on the internet and I couldn't find what I needed.

I need to be able to figure out which block they would break or where a new block would go based of the side they are looking at.

I need to find which face of which cube I am looking at. This is the code I made but some of the math must be off because it isn't working.

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
Hippolippo
  • 803
  • 1
  • 5
  • 28
  • Given the user position and view direction, you can just traverse the 3D grid and pick the first occupied cell. See [this answer](https://stackoverflow.com/questions/49188302/how-can-you-iterate-linearly-through-a-3d-grid/49188546#49188546). – Nico Schertler Feb 22 '19 at 04:49
  • @NicoSchertler all of my cubes are the same size and they are in a grid, I need a simpler answer that doesn't involve sizes – Hippolippo Feb 23 '19 at 16:22
  • That answer assumes uniform sizes. It does not get much simpler than that – Nico Schertler Feb 23 '19 at 16:52
  • @NicoSchertler ok, I will look at that – Hippolippo Feb 23 '19 at 16:52
  • @NicoSchertler Could you show what each of the variables is referring to and maybe how I could apply that to what I am trying to do? – Hippolippo Feb 25 '19 at 22:31
  • @NicoSchertler and how would you use that to determine which face they are looking at – Hippolippo Feb 25 '19 at 22:43
  • Possible duplicate of [How can you iterate linearly through a 3D grid?](https://stackoverflow.com/questions/49188302/how-can-you-iterate-linearly-through-a-3d-grid) – BDL Feb 28 '19 at 09:35
  • @BDL that isn't an answer to my question. I don't have and ray to traverse whatever that means or cells or anything. I need to know what face of what cube someone is looking at. Please help me, this is due in a week. – Hippolippo Mar 01 '19 at 21:47

1 Answers1

0

You could make a sphere of contact around the player and use a radius "protruding" from the player's face.

Radius r would be the maximum distance the user could look at a block and still be able to affect it.

Using triangles you could detect if the end of the radius is inside a block or not, etc.

JoshDaBosh
  • 396
  • 2
  • 6