def hit(self, blocks, max_distance=8, left=True): """Line of sight search from current position. If a block is intersected it is returned, along with the block previously in the line of sight. If no block is found, return None, None. Parameters ---------- blocks : dict A mapping from position to the texture of a block max_distance : int How many blocks away to search for a hit. left : bool hit is called by left-click or not """ m = 8 x, y, z = self.position head, feet = normalize((x, y, z)), normalize((x, y - 1, z)) dx, dy, dz = self.get_sight_vector() previous = None for _ in range(max_distance * m): key = normalize((x, y, z)) if key != previous and key in blocks: if not left and (previous == head or previous == feet): continue # Make sure the block isn't the player's head or feet in case of adding. return key, previous previous = key x, y, z = x + dx / m, y + dy / m, z + dz / m return None, None
def hit_test(self, position, vector, max_distance=8): """Line of sight search from current position. If a block is intersected it is returned, along with the block previously in the line of sight. If no block is found, return None, None. Parameters ---------- position : tuple of len 3 The (x, y, z) position to check visibility from. vector : tuple of len 3 The line of sight vector. max_distance : int How many blocks away to search for a hit. """ m = 8 x, y, z = position dx, dy, dz = vector previous = None for _ in range(max_distance * m): key = normalize((x, y, z)) if key != previous and key in self.objects: return key, previous previous = key x, y, z = x + dx / m, y + dy / m, z + dz / m return None, None
def hit_test(self, coords, vector, max_distance=8): """Line of sight search from current position. If a block is intersected it is returned, along with the block previously in the line of sight. If no block is found, return None, None. Parameters ---------- coords : tuple of len 3 The (x, y, z) position to check visibility from. vector : tuple of len 3 The line of sight vector. max_distance : int How many blocks away to search for a hit. """ m = 8 x, y, z = coords dx, dy, dz = vector previous = None for _ in range(max_distance * m): key = normalize((x, y, z)) if key != previous and key in self.blocks: return key, previous previous = key x, y, z = x + dx / m, y + dy / m, z + dz / m return None, None
def on_joybutton_press(self, joystick, button): vector = self.player.get_sight_vector() block, previous = self.world.hit_test(self.player.position, vector) if button == 0: player_x, player_y, player_z = normalize(self.player.position) if previous and previous != (player_x, player_y, player_z) and \ previous != (player_x, player_y - 1, player_z): # make sure the block isn't in the players head or feet if self.player.current_item: self.world.add_block(previous, get_block(self.player.get_block())) elif button == 1: self.player.jump() elif button == 2 and block: texture = self.world.objects[block] if texture.hit_and_destroy(): self.world.remove_block(block) elif button == 3: self.player.fly() elif button == 4: self.player.previous_inventory_item() elif button == 5: self.player.next_inventory_item() print('Button %s pressed' % button)
def test_normalize(): """ Test the normalize function. """ my_pos = [3.29, 5.9, 7.001] expected = [3, 5, 7] norm_pos = util.normalize(my_pos) for i, e in zip(norm_pos, expected): assert isinstance(i, int), "Returned position not an integer" assert i == e, "Returned postion ({}) not what we expected ({})!".format(i, e)
def test_normalize(): """ Test the normalize function. """ my_pos = [3.29, 5.9, 7.001] expected = [3, 6, 7] norm_pos = util.normalize(my_pos) for i, e in zip(norm_pos, expected): assert isinstance(i, int), "Returned position not an integer" assert i == e, "Returned postion ({}) not what we expected ({})!".format( i, e)
def on_mouse_press(self, x, y, button, modifiers): vector = self.player.get_sight_vector() block, previous = self.world.hit_test(self.player.position, vector) if (button == mouse.RIGHT) or \ ((button == mouse.LEFT) and (modifiers & key.MOD_CTRL)): # ON OSX, control + left click = right click. player_x, player_y, player_z = normalize(self.player.position) if previous and previous != (player_x, player_y, player_z) and \ previous != (player_x, player_y - 1, player_z): # make sure the block isn't in the players head or feet if self.player.current_item: self.world.add_block(previous, get_block(self.player.get_block())) elif button == pyglet.window.mouse.LEFT and block: texture = self.world.objects[block] if texture.hit_and_destroy(): self.world.remove_block(block)
def on_mouse_press(self, x, y, button, modifiers): vector = self.player.get_sight_vector() block, previous = self.world.hit_test(self.player.position, vector) if (button == mouse.RIGHT) or \ ((button == mouse.LEFT) and (modifiers & key.MOD_CTRL)): # ON OSX, control + left click = right click. player_x, player_y, player_z = normalize(self.player.position) if previous and self.player.block and \ previous != (player_x, player_y, player_z) and \ previous != (player_x, player_y - 1, player_z): # make sure the block isn't in the players head or feet self.world.add_block(previous, get_block(self.player.block)) self.player.adjust_inventory(self.player.block) elif button == pyglet.window.mouse.LEFT and block: texture = self.world.objects[block] if texture.hit_and_destroy(): self.world.remove_block(block)
def collide(self, position, height, objects): """Checks to see if the player at the given `position` and `height` is colliding with any blocks in the world. Parametesrs ---------- position : tuple of len 3 The (x, y, z) position to check for collisions at. height : int or float The height of the player. Returns ------- position : tuple of len 3 The new position of the player taking into account collisions. """ # How much overlap with a dimension of a surrounding block you need to # have to count as a collision. If 0, touching terrain at all counts as # a collision. If .49, you sink into the ground, as if walking through # tall grass. If >= .5, you'll fall through the ground. pad = 0.25 p = list(position) np = normalize(position) for face in FACES: # check all surrounding blocks for i in range(3): # check each dimension independently if not face[i]: continue # How much overlap you have with this dimension. d = (p[i] - np[i]) * face[i] if d < pad: continue for dy in range(height): # check each height op = list(np) op[1] -= dy op[i] += face[i] if tuple(op) not in objects: continue p[i] -= (d - pad) * face[i] if face == (0, -1, 0) or face == (0, 1, 0): # You are colliding with the ground or ceiling, so stop # falling / rising. self.dy = 0 break return tuple(p)
def on_mouse_press(self, x, y, button, modifiers): """Called when a mouse button is pressed. See pyglet docs for button amd modifier mappings. Parameters ---------- x, y : int The coordinates of the mouse click. Always center of the screen if the mouse is captured. button : int Number representing mouse button that was clicked. 1 = left button, 4 = right button. modifiers : int Number representing any modifying keys that were pressed when the mouse button was clicked. """ if self.exclusive: vector = self.player.get_sight_vector() block, previous = self.world.hit_test(self.player.position, vector) if (button == mouse.RIGHT) or \ ((button == mouse.LEFT) and (modifiers & key.MOD_CTRL)): # ON OSX, control + left click = right click. player_x, player_y, player_z = normalize(self.player.position) if previous and self.player.block and \ previous != (player_x, player_y, player_z) and \ previous != (player_x, player_y-1, player_z): # make sure the block isn't in the players head or feet self.world.add_block(previous, get_block(self.player.block)) self.player.adjust_inventory(self.player.block) elif button == pyglet.window.mouse.LEFT and block: texture = self.world.objects[block] if texture.breakable: self.world.remove_block(block) else: self.set_exclusive_mouse(True)
def on_mouse_press(self, x, y, button, modifiers): """Called when a mouse button is pressed. See pyglet docs for button amd modifier mappings. Parameters ---------- x, y : int The coordinates of the mouse click. Always center of the screen if the mouse is captured. button : int Number representing mouse button that was clicked. 1 = left button, 4 = right button. modifiers : int Number representing any modifying keys that were pressed when the mouse button was clicked. """ if self.exclusive: vector = self.player.get_sight_vector() block, previous = self.world.hit_test(self.player.position, vector) if (button == mouse.RIGHT) or \ ((button == mouse.LEFT) and (modifiers & key.MOD_CTRL)): # ON OSX, control + left click = right click. player_x, player_y, player_z = normalize(self.player.position) if previous and self.player.block and \ previous != (player_x, player_y, player_z) and \ previous != (player_x, player_y - 1, player_z): # make sure the block isn't in the players head or feet self.world.add_block(previous, get_block(self.player.block)) self.player.adjust_inventory(self.player.block) elif button == pyglet.window.mouse.LEFT and block: texture = self.world.objects[block] if texture.hit_and_destroy(): self.world.remove_block(block) else: self.set_exclusive_mouse(True)