Get the players direction / find out where they are looking

184 views
Skip to first unread message

Martin O'Hanlon

unread,
Jan 13, 2015, 4:31:41 PM1/13/15
to adventures-in-...@googlegroups.com
This has been a common request for the Minecraft API, how can I find out where the player is looking so I decided to add it to RaspberryJuice, unfortunately I cant add it to the Minecraft: Pi Edition, so this only works on the full version of Minecraft (sorry - blame Mojang)

Check out my blog post http://www.stuffaboutcode.com/2015/01/minecraft-api-players-direction.html where you will also find a video.

I have put the new version of RaspberryJuice into the 1.7.10 canarymod starter kit, so if you want to try it out download the latest version.

David Whale

unread,
Jan 14, 2015, 3:50:04 AM1/14/15
to adventures-in-...@googlegroups.com
The closest I ever got in Minecraft Pi edition to working out the players direction, is to monitor changes in the x, y and z coordinates each time round the game loop, and turn these deltas into directions of movement. So, if x gets smaller between two loops of the game loop, then you know the player is moving in the negative x direction. The same can be applied to y and z. This can be translated into a function that indicates present move direction (not facing direction). You could make a simple assumption that you are facing the direction you are moving (which would be correct most of the time).

It's only an approximation, but it does work, and the maths involved is well within that of an 11 year old to understand, and the computational thinking required to develop this solution makes quite a good workshop.

Here is the code I use to "approximate" movement and facing directions:

# direction.py  14/01/2015  D.J.Whale
#
# Show how to 'guess' at the players move/facing direction in Minecraft Pi edition

import mcpi.minecraft as minecraft
import time

# Rate (in seconds) to report updates to chat
REPORT_RATE = 1

# How long you stand still (in seconds) before the "facing" direction is invalidated
FACING_TIMEOUT = 4

# Create a connection to minecraft
mc = minecraft.Minecraft.create()

# Sample the initial position
pos = mc.player.getTilePos()
xold = pos.x
yold = pos.y
zold = pos.z

# These 3 variables maintain movement direction information (0=none)
mxdirn = 0
mydirn = 0
mzdirn = 0

# These 3 variables maintain facing direction information (0=unknown)
fxdirn = 0
fydirn = 0
fzdirn = 0

# Use time() horizons, so we can run the game loop quickly to avoid
# glitching in sampling directions, but still report messages on the
# chat at a slowish rate
lastReportTime = time.time()
lastMoveTime = time.time()


def dirn(old, new):
    """Turn two values into a signed direction (ignoring magnitude)"""
    if new > old:
        return +1
    elif new < old:
        return -1
    return 0


def compass(d, minus, plus):
    """Turn a direction into text"""
    if d > 0:
        return plus
    elif d < 0:
        return minus
    return ""


def updateMoving():
    """Sample players direction and update variables"""
    global mxdirn, mydirn, mzdirn, xold, yold, zold, lastMoveTime

    # Sample players movement direction each time round the loop
    pos = mc.player.getTilePos()
    mxdirn = dirn(xold, pos.x)
    mydirn = dirn(yold, pos.y)
    mzdirn = dirn(zold, pos.z)

    # If we have moved, remember time we moved, and update old position
    if mxdirn !=0 or mydirn != 0 or mydirn != 0:
        lastMoveTime = time.time()
        
    # Update old position   
    xold = pos.x
    yold = pos.y
    zold = pos.z


def updateFacing():
    """Update the facing direction based on the movement direction"""
    global fxdirn, fydirn, fzdirn
    
    # The facing direction is a sticky version of the movement direction
    # i.e. if moving, update facing direction, else remember old facing direction

    if mxdirn != 0 or mydirn !=0 or mzdirn != 0:
        # we are moving, so set facing direction to moving direction
        fxdirn = mxdirn
        fydirn = mydirn
        fzdirn = mzdirn
        
    else:
        # we are not moving, timeout the sticky facing direction after FACING_TIMEOUT
        # so that if you don't move for ages, we "invalidate" the facing estimation as it
        # has a high probability of being wrong.
        nowtime = time.time()
        if nowtime > lastMoveTime + FACING_TIMEOUT:
            fxdirn = 0
            fydirn = 0
            fzdirn = 0
        


def getMoving():
    if mxdirn != 0 or mydirn != 0 or mzdirn != 0:
        # player is moving
        return ("Moving: "  
            + compass(mzdirn, "north", "south") + " "
            + compass(mxdirn, "west", "east") + " "
            + compass(mydirn, "down", "up"))
    else:
        return "Not Moving"
    

def getFacing():
    if fxdirn != 0 or fydirn !=0 or fzdirn != 0L:
        # Facing direction is known
        return ("Facing: "
            + compass(fzdirn, "north", "south") + " "
            + compass(fxdirn, "west", "east") + " "
            + compass(fydirn, "down", "up"))
    else:
        return "Not sure which way you are facing"
    

# Game loop

while True:
    time.sleep(0.1)
    updateMoving()
    updateFacing()

    # Report movement direction and facing direction on chat, every few seconds
    now = time.time()
    if now > lastReportTime + REPORT_RATE:
        lastReportTime = now
        
        mc.postToChat(getFacing())

        if mxdirn !=0 or mydirn != 0 or mzdirn != 0:
            # Only report movement direction if player is moving
            mc.postToChat(getMoving())
# END

    
In a later instalment to this blog post, I will show how you can turn all of this code into a single function that can be called from your Minecraft programs, so that it operates in the same way as Martin's new RaspberryJuice functions that he talks about above. That will then allow you to make decisions in your programs such as "if the player is facing north, play music, else if the player is moving east, leave a lava trail".

David
@whaleygeek
Reply all
Reply to author
Forward
0 new messages