예제 #1
0
class Player(Entity):
    local_player = True

    def __init__(self,
                 position=(0, 0, 0),
                 rotation=(-20, 0),
                 flying=False,
                 game_mode=G.GAME_MODE,
                 username="",
                 local_player=True):
        super(Player, self).__init__(position,
                                     rotation,
                                     health=7,
                                     max_health=10,
                                     attack_power=2.0 / 3,
                                     attack_range=4)
        self.inventory = Inventory(27)
        self.quick_slots = Inventory(9)
        self.armor = Inventory(4)
        self.flying = flying
        self.game_mode = game_mode
        self.strafe = [0, 0]
        self.dy = 0
        self.current_density = 1  # Current density of the block we're colliding with
        self._position = position
        self.last_sector = None
        self.last_damage_block = 0, 100, 0  # dummy temp value
        self.username = username
        self.local_player = local_player

        # for debug
        initial_items = [cake_block, torch_block, bed_item]
        for item in initial_items:
            self.inventory.add_item(item.id, item.max_stack_size)

        if not local_player:
            self.model = PlayerModel(position)
            self.momentum = (0, 0, 0)

    def add_item(self, item_id, quantity=1):
        if self.quick_slots.add_item(item_id, quantity=quantity):
            return True
        elif self.inventory.add_item(item_id, quantity=quantity):
            return True
        return False

    def change_health(self, change):
        self.health += change
        if self.health > self.max_health:
            self.health = self.max_health

    @property
    def position(self):
        return self._position

    @position.setter
    def position(self, value):
        self._position = value
        if not self.local_player: self.model.update_position(value)

    def on_deactivate(self):
        self.strafe = [0, 0]

    def on_key_release(self, symbol, modifiers):
        if symbol == G.MOVE_FORWARD_KEY:
            self.strafe[0] += 1
        elif symbol == G.MOVE_BACKWARD_KEY:
            self.strafe[0] -= 1
        elif symbol == G.MOVE_LEFT_KEY:
            self.strafe[1] += 1
        elif symbol == G.MOVE_RIGHT_KEY:
            self.strafe[1] -= 1
        elif (symbol == G.JUMP_KEY or symbol == G.CROUCH_KEY) and self.flying:
            self.dy = 0

    def on_key_press(self, symbol, modifiers):
        if symbol == G.MOVE_FORWARD_KEY:
            self.strafe[0] -= 1
        elif symbol == G.MOVE_BACKWARD_KEY:
            self.strafe[0] += 1
        elif symbol == G.MOVE_LEFT_KEY:
            self.strafe[1] -= 1
        elif symbol == G.MOVE_RIGHT_KEY:
            self.strafe[1] += 1
        elif symbol == G.JUMP_KEY:
            if self.flying:
                self.dy = 0.045  # jump speed
            elif self.dy == 0:
                self.dy = 0.016  # jump speed
                G.CLIENT.send_jump()
        elif symbol == G.CROUCH_KEY:
            if self.flying:
                self.dy = -0.045  # inversed jump speed
        elif symbol == G.FLY_KEY and self.game_mode == G.CREATIVE_MODE:
            self.dy = 0
            self.flying = not self.flying

    def get_motion_vector(self, multiplier=1):
        if any(self.strafe):
            x, y = self.rotation
            y_r = radians(y)
            x_r = radians(x)
            strafe = atan2(*self.strafe)
            if self.flying:
                m = cos(y_r)
                dy = sin(y_r)
                if self.strafe[1]:
                    dy = 0.0
                    m = 1
                if self.strafe[0] > 0:
                    dy *= -1
                x_r += strafe
                dx = cos(x_r) * m
                dz = sin(x_r) * m
            else:
                dy = 0.0
                x_r += strafe
                dx = cos(x_r)
                dz = sin(x_r)
        else:
            dy = 0.0
            dx = 0.0
            dz = 0.0
        return dx * multiplier, dy * multiplier, dz * multiplier  # Replace index 1 with dy*multiplier

    def get_sight_vector(self):
        x, y = self.rotation
        y_r = radians(y)
        x_r = radians(x)
        m = cos(y_r)
        dy = sin(y_r)
        x_r -= G.HALF_PI
        dx = cos(x_r) * m
        dz = sin(x_r) * m
        return dx, dy, dz

    # get sight direction
    # retval[0]: E/S/W/N
    # retval[1]: angle between sight vector and east direction
    def get_sight_direction(self):
        dx, dy, dz = self.get_sight_vector()
        dz = -dz

        angle = 0
        if dz == 0:
            if dx > 0:
                angle = 0
            elif dx < 0:
                angle = pi
        elif dz > 0:
            angle = acos(dx / sqrt(dx * dx + dz * dz))
        else:
            angle = -acos(dx / sqrt(dx * dx + dz * dz))

        if angle < 0: angle += 2 * pi

        angle *= 180 / pi

        if 0 < angle <= 45 or 315 < angle <= 360:
            direction = G.EAST
        elif 45 < angle <= 135:
            direction = G.NORTH
        elif 135 < angle <= 225:
            direction = G.WEST
        elif 225 < angle <= 315:
            direction = G.SOUTH

        return (dx, dy, dz), direction, angle

    def update(self, dt, parent):
        # walking
        if self.local_player:
            speed = 15 if self.flying else 5 * self.current_density
            dx, dy, dz = self.get_motion_vector(multiplier=(dt * speed))
        else:
            dx, dy, dz = self.momentum
            dx, dy, dz = dx * dt, dy * dt, dz * dt

        # gravity
        if not self.flying:
            self.dy -= dt * 0.022  # g force, should be = jump_speed * 0.5 / max_jump_height
        self.dy = max(self.dy, -0.5)  # terminal velocity
        dy += self.dy

        # collisions
        x, y, z = self.position
        self.position = self.collide(parent, (x + dx, y + dy, z + dz), 2)

    def collide(self, parent, position, height):
        pad = 0.25
        p = list(position)
        np = normalize(position)
        self.current_density = 1  # Reset it, incase we don't hit any water
        for face in FACES:  # check all surrounding blocks
            for i in range(3):  # check each dimension independently
                if not face[i]:
                    continue
                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]
                    op = tuple(op)
                    # If there is no block or if the block is not a cube,
                    # we can walk there.
                    if op not in parent.world \
                            or parent.world[op].vertex_mode != G.VERTEX_CUBE:
                        continue
                    # if density <= 1 then we can walk through it. (water)
                    if parent.world[op].density < 1:
                        self.current_density = parent.world[op].density
                        continue
                    # if height <= 1 then we can walk on top of it. (carpet, half-blocks, etc...)
                    if parent.world[op].height < 0.5:
                        #current_height = parent.world[op].height
                        #x, y, z = self.position
                        #new_pos = (x, y + current_height, z)
                        #self.position = new_pos
                        continue

                    if parent.world[op].player_damage > 0:
                        if self.last_damage_block != np:
                            # this keeps a player from taking the same damage over and over...
                            self.change_health(-parent.world[op].player_damage)
                            parent.item_list.update_health()
                            self.last_damage_block = np
                            continue
                        else:
                            #do nothing
                            continue

                    p[i] -= (d - pad) * face[i]
                    if face == (0, -1, 0) or face == (0, 1, 0):
                        # jump damage
                        if self.game_mode == G.SURVIVAL_MODE:
                            damage = self.dy * -1000.0
                            damage = 3.0 * damage / 22.0
                            damage -= 2.0
                            if damage >= 0.0:
                                health_change = 0
                                if damage <= 0.839:
                                    health_change = 0
                                elif damage <= 1.146:
                                    health_change = -1
                                elif damage <= 1.44:
                                    health_change = -2
                                elif damage <= 2.26:
                                    health_change = -2
                                else:
                                    health_change = -3
                                if health_change != 0:
                                    self.change_health(health_change)
                                    parent.item_list.update_health()
                        self.dy = 0
                    break
        return tuple(p)
예제 #2
0
class Player(Entity):
    local_player = True

    def __init__(self, position=(0,0,0), rotation=(-20, 0), flying=False,
                 game_mode=G.GAME_MODE, username="", local_player=True):
        super(Player, self).__init__(position, rotation, health=7,
                                     max_health=10, attack_power=2.0 / 3,
                                     attack_range=4)
        self.inventory = Inventory(27)
        self.quick_slots = Inventory(9)
        self.armor = Inventory(4)
        self.flying = flying
        self.game_mode = game_mode
        self.strafe = [0, 0]
        self.dy = 0
        self.current_density = 1 # Current density of the block we're colliding with
        self._position = position
        self.last_sector = None
        self.last_damage_block = 0, 100, 0 # dummy temp value
        self.username = username
        self.local_player = local_player

        # for debug
        initial_items = [cake_block, torch_block, bed_item]
        for item in initial_items:
            self.inventory.add_item(item.id, item.max_stack_size)

        if not local_player:
            self.model = PlayerModel(position)
            self.momentum = (0,0,0)

    def add_item(self, item_id, quantity=1):
        if self.quick_slots.add_item(item_id, quantity=quantity):
            return True
        elif self.inventory.add_item(item_id, quantity=quantity):
            return True
        return False

    def change_health(self, change):
        self.health += change
        if self.health > self.max_health:
            self.health = self.max_health
    @property
    def position(self):
        return self._position

    @position.setter
    def position(self, value):
        self._position = value
        if not self.local_player: self.model.update_position(value)

    def on_deactivate(self):
        self.strafe = [0, 0]

    def on_key_release(self, symbol, modifiers):
        if symbol == G.MOVE_FORWARD_KEY:
            self.strafe[0] += 1
        elif symbol == G.MOVE_BACKWARD_KEY:
            self.strafe[0] -= 1
        elif symbol == G.MOVE_LEFT_KEY:
            self.strafe[1] += 1
        elif symbol == G.MOVE_RIGHT_KEY:
            self.strafe[1] -= 1
        elif (symbol == G.JUMP_KEY
              or symbol == G.CROUCH_KEY) and self.flying:
            self.dy = 0

    def on_key_press(self, symbol, modifiers):
        if symbol == G.MOVE_FORWARD_KEY:
            self.strafe[0] -= 1
        elif symbol == G.MOVE_BACKWARD_KEY:
            self.strafe[0] += 1
        elif symbol == G.MOVE_LEFT_KEY:
            self.strafe[1] -= 1
        elif symbol == G.MOVE_RIGHT_KEY:
            self.strafe[1] += 1
        elif symbol == G.JUMP_KEY:
            if self.flying:
                self.dy = 0.045  # jump speed
            elif self.dy == 0:
                self.dy = 0.016  # jump speed
                G.CLIENT.send_jump()
        elif symbol == G.CROUCH_KEY:
            if self.flying:
                self.dy = -0.045  # inversed jump speed
        elif symbol == G.FLY_KEY and self.game_mode == G.CREATIVE_MODE:
            self.dy = 0
            self.flying = not self.flying

    def get_motion_vector(self, multiplier=1):
        if any(self.strafe):
            x, y = self.rotation
            y_r = radians(y)
            x_r = radians(x)
            strafe = atan2(*self.strafe)
            if self.flying:
                m = cos(y_r)
                dy = sin(y_r)
                if self.strafe[1]:
                    dy = 0.0
                    m = 1
                if self.strafe[0] > 0:
                    dy *= -1
                x_r += strafe
                dx = cos(x_r) * m
                dz = sin(x_r) * m
            else:
                dy = 0.0
                x_r += strafe
                dx = cos(x_r)
                dz = sin(x_r)
        else:
            dy = 0.0
            dx = 0.0
            dz = 0.0
        return dx*multiplier, dy*multiplier, dz*multiplier

    def get_sight_vector(self):
        x, y = self.rotation
        y_r = radians(y)
        x_r = radians(x)
        m = cos(y_r)
        dy = sin(y_r)
        x_r -= G.HALF_PI
        dx = cos(x_r) * m
        dz = sin(x_r) * m
        return dx, dy, dz

    # get sight direction
    # retval[0]: E/S/W/N
    # retval[1]: angle between sight vector and east direction
    def get_sight_direction(self):
        dx, dy, dz = self.get_sight_vector()
        dz = -dz

        angle = 0
        if dz == 0:
            if dx > 0:
                angle = 0
            elif dx < 0:
                angle = pi
        elif dz > 0:
            angle = acos(dx / sqrt(dx * dx + dz * dz))
        else:
            angle = -acos(dx / sqrt(dx * dx + dz * dz))

        if angle < 0: angle += 2 * pi

        angle *= 180 / pi

        if 0 < angle <= 45 or 315 < angle <= 360:
            direction = G.EAST
        elif 45 < angle <= 135:
            direction = G.NORTH
        elif 135 < angle <= 225:
            direction = G.WEST
        elif 225 < angle <= 315:
            direction = G.SOUTH

        return (dx, dy, dz), direction, angle

    def update(self, dt, parent):
        # walking
        if self.local_player:
            speed = 15 if self.flying else 5*self.current_density
            dx, dy, dz = self.get_motion_vector(multiplier=(dt * speed))
        else:
            dx, dy, dz = self.momentum
            dx, dy, dz = dx*dt, dy*dt, dz*dt

        # gravity
        if not self.flying:
            self.dy -= dt * 0.022  # g force, should be = jump_speed * 0.5 / max_jump_height
        self.dy = max(self.dy, -0.5)  # terminal velocity
        dy += self.dy

        # collisions
        x, y, z = self.position
        self.position = self.collide(parent, (x + dx, y + dy, z + dz), 2)

    def collide(self, parent, position, height):
        pad = 0.25
        p = list(position)
        np = normalize(position)
        self.current_density = 1 # Reset it, incase we don't hit any water
        for face in FACES:  # check all surrounding blocks
            for i in xrange(3):  # check each dimension independently
                if not face[i]:
                    continue
                d = (p[i] - np[i]) * face[i]
                if d < pad:
                    continue
                for dy in xrange(height):  # check each height
                    op = list(np)
                    op[1] -= dy
                    op[i] += face[i]
                    op = tuple(op)
                    # If there is no block or if the block is not a cube,
                    # we can walk there.
                    if op not in parent.world \
                            or parent.world[op].vertex_mode != G.VERTEX_CUBE:
                        continue
                    # if density <= 1 then we can walk through it. (water)
                    if parent.world[op].density < 1:
                        self.current_density = parent.world[op].density
                        continue
                    # if height <= 1 then we can walk on top of it. (carpet, half-blocks, etc...)
                    if parent.world[op].height < 0.5:
                        #current_height = parent.world[op].height
                        #x, y, z = self.position
                        #new_pos = (x, y + current_height, z)
                        #self.position = new_pos
                        continue

                    if parent.world[op].player_damage > 0:
                        if self.last_damage_block != np:
                            # this keeps a player from taking the same damage over and over...
                            self.change_health( - parent.world[op].player_damage)
                            parent.item_list.update_health()
                            self.last_damage_block = np
                            continue
                        else:
                            #do nothing
                            continue


                    p[i] -= (d - pad) * face[i]
                    if face == (0, -1, 0) or face == (0, 1, 0):
                        # jump damage
                        if self.game_mode == G.SURVIVAL_MODE:
                            damage = self.dy * -1000.0
                            damage = 3.0 * damage / 22.0
                            damage -= 2.0
                            if damage >= 0.0:
                                health_change = 0
                                if damage <= 0.839:
                                    health_change = 0
                                elif damage <= 1.146:
                                    health_change = -1
                                elif damage <= 1.44:
                                    health_change = -2
                                elif damage <= 2.26:
                                    health_change = -2
                                else:
                                    health_change = -3
                                if health_change != 0:
                                    self.change_health(health_change)
                                    parent.item_list.update_health()
                        self.dy = 0
                    break
        return tuple(p)
예제 #3
0
class Mob(Entity):
    local_player = True

    def __init__(self, loc, position=(0, 0, 0), rotation=(-20, 0)):
        super(Mob, self).__init__(position, rotation)
        self.model = PlayerModel(position, True, loc=loc)
        self.momentum = (0, 0, 0)

    def get_motion_vector(self, multiplier=1):
        if any(self.strafe):
            x, y = self.rotation
            x_r = radians(x)
            strafe = atan2(*self.strafe)
            dy = 0.0
            x_r += strafe
            dx = cos(x_r)
            dz = sin(x_r)
        else:
            dy = 0.0
            dx = 0.0
            dz = 0.0
        return dx * multiplier, dy * multiplier, dz * multiplier

    def change_health(self, change):
        self.health += change
        if self.health > self.max_health:
            self.health = self.max_health

    @property
    def position(self):
        return self._position

    @position.setter
    def position(self, value):
        self._position = value
        self.model.update_position(value)

    def on_deactivate(self):
        self.strafe = [0, 0]

    def get_sight_vector(self):
        x, y = self.rotation
        y_r = radians(y)
        x_r = radians(x)
        m = cos(y_r)
        dy = sin(y_r)
        x_r -= G.HALF_PI
        dx = cos(x_r) * m
        dz = sin(x_r) * m
        return dx, dy, dz

    # get sight direction
    # retval[0]: E/S/W/N
    # retval[1]: angle between sight vector and east direction
    def get_sight_direction(self):
        dx, dy, dz = self.get_sight_vector()
        dz = -dz

        angle = 0
        if dz == 0:
            if dx > 0:
                angle = 0
            elif dx < 0:
                angle = pi
        elif dz > 0:
            angle = acos(dx / sqrt(dx * dx + dz * dz))
        else:
            angle = -acos(dx / sqrt(dx * dx + dz * dz))

        if angle < 0: angle += 2 * pi

        angle *= 180 / pi

        if 0 < angle <= 45 or 315 < angle <= 360:
            direction = G.EAST
        elif 45 < angle <= 135:
            direction = G.NORTH
        elif 135 < angle <= 225:
            direction = G.WEST
        elif 225 < angle <= 315:
            direction = G.SOUTH
        else:
            raise RotationError()
        return (dx, dy, dz), direction, angle

    def update(self, dt, parent):
        # walking
        speed = 5 * self.current_density
        dx, dy, dz = self.get_motion_vector(multiplier=(dt * speed))

        # gravity
        self.dy -= dt * 0.022  # g force, should be = jump_speed * 0.5 / max_jump_height
        self.dy = max(self.dy, -0.5)  # terminal velocity
        dy += self.dy

        # collisions
        x, y, z = self.position
        self.position = self.collide(parent, (x + dx, y + dy, z + dz), 2)

    def collide(self, parent, position, height):
        pad = 0.25
        p = list(position)
        np = normalize(position)
        self.current_density = 1  # Reset it, incase we don't hit any water
        for face in FACES:  # check all surrounding blocks
            for i in range(3):  # check each dimension independently
                if not face[i]:
                    continue
                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]
                    op = tuple(op)
                    # If there is no block or if the block is not a cube,
                    # we can walk there.
                    if op not in parent.world \
                            or parent.world[op].vertex_mode != G.VERTEX_CUBE:
                        continue
                    # if density <= 1 then we can walk through it. (water)
                    if parent.world[op].density < 1:
                        self.current_density = parent.world[op].density
                        continue
                    # if height <= 1 then we can walk on top of it. (carpet, half-blocks, etc...)
                    if parent.world[op].height < 0.5:
                        # current_height = parent.world[op].height
                        # x, y, z = self.position
                        # new_pos = (x, y + current_height, z)
                        # self.position = new_pos
                        continue

                    if parent.world[op].player_damage > 0:
                        if self.last_damage_block != np:
                            # this keeps a player from taking the same damage over and over...
                            self.change_health(-parent.world[op].player_damage)
                            parent.item_list.update_health()
                            self.last_damage_block = np
                            continue
                        else:
                            # do nothing
                            continue

                    p[i] -= (d - pad) * face[i]
                    if face == (0, -1, 0) or face == (0, 1, 0):
                        # jump damage
                        damage = self.dy * -1000.0
                        damage = 3.0 * damage / 22.0
                        damage -= 2.0
                        if damage >= 0.0:
                            health_change = 0
                            if damage <= 0.839:
                                health_change = 0
                            elif damage <= 1.146:
                                health_change = -1
                            elif damage <= 1.44:
                                health_change = -2
                            elif damage <= 2.26:
                                health_change = -2
                            else:
                                health_change = -3
                            if health_change != 0:
                                self.change_health(health_change)
                                parent.item_list.update_health()
                        self.dy = 0
                    break
        return tuple(p)