Пример #1
0
    def load_program(
            self,
            *,
            vertex_shader: Union[str, Path],
            fragment_shader: Union[str, Path] = None,
            geometry_shader: Union[str, Path] = None,
            defines: dict = None) -> Program:
        """Create a new program given a file names that contain the vertex shader and
        fragment shader.

        :param Union[str,pathlib.Path] vertex_shader: path to vertex shader
        :param Union[str,pathlib.Path] fragment_shader: path to fragment shader
        :param Union[str,pathlib.Path] geometry_shader: path to geometry shader
        :param dict defines: Substitute ``#define`` values in the source
        """
        from arcade.resources import resolve_resource_path

        vertex_shader_src = resolve_resource_path(vertex_shader).read_text()
        fragment_shader_src = None
        geometry_shader_src = None

        if fragment_shader:
            fragment_shader_src = resolve_resource_path(fragment_shader).read_text()

        if geometry_shader:
            geometry_shader_src = resolve_resource_path(geometry_shader).read_text()

        return self.program(
            vertex_shader=vertex_shader_src,
            fragment_shader=fragment_shader_src,
            geometry_shader=geometry_shader_src,
            defines=defines,
        )
Пример #2
0
    def load_program(
        self,
        *,
        vertex_shader: Union[str, Path],
        fragment_shader: Union[str, Path] = None,
        geometry_shader: Union[str, Path] = None,
        tess_control_shader: Union[str, Path] = None,
        tess_evaluation_shader: Union[str, Path] = None,
        defines: dict = None,
    ) -> Program:
        """Create a new program given a file names that contain the vertex shader and
        fragment shader. Note that fragment and geometry shader are optional for
        when transform shaders are loaded.

        This method also supports the ``:resources:`` prefix.
        It's recommended to use absolute paths, but not required.

        Example::

            # The most common use case if having a vertex and fragment shader
            program = window.ctx.load_program(
                vertex_shader="vert.glsl",
                fragment_shader="frag.glsl",
            )

        :param Union[str,pathlib.Path] vertex_shader: path to vertex shader
        :param Union[str,pathlib.Path] fragment_shader: path to fragment shader (optional)
        :param Union[str,pathlib.Path] geometry_shader: path to geometry shader (optional)
        :param dict defines: Substitute ``#define`` values in the source
        """
        from arcade.resources import resolve_resource_path

        vertex_shader_src = resolve_resource_path(vertex_shader).read_text()
        fragment_shader_src = None
        geometry_shader_src = None
        tess_control_src = None
        tess_evaluation_src = None

        if fragment_shader:
            fragment_shader_src = resolve_resource_path(fragment_shader).read_text()

        if geometry_shader:
            geometry_shader_src = resolve_resource_path(geometry_shader).read_text()

        if tess_control_shader and tess_evaluation_shader:
            tess_control_src = resolve_resource_path(tess_control_shader).read_text()
            tess_evaluation_src = resolve_resource_path(tess_evaluation_shader).read_text()

        return self.program(
            vertex_shader=vertex_shader_src,
            fragment_shader=fragment_shader_src,
            geometry_shader=geometry_shader_src,
            tess_control_shader=tess_control_src,
            tess_evaluation_shader=tess_evaluation_src,
            defines=defines,
        )
Пример #3
0
    def load_texture(
        self,
        path: Union[str, Path],
        *,
        flip: bool = True,
        build_mipmaps=False,
    ) -> Texture:
        """Loads and creates an OpenGL 2D texture.
        Currently all textures are converted to RGBA.

        Example::

            texture = window.ctx.load_texture("background.png")

        :param Union[str,pathlib.Path] path: Path to texture
        :param bool flip: Flips the image upside down
        :param bool build_mipmaps: Build mipmaps for the texture
        """
        from arcade.resources import resolve_resource_path
        path = resolve_resource_path(path)

        image = Image.open(str(path))

        if flip:
            image = image.transpose(Image.FLIP_TOP_BOTTOM)

        texture = self.texture(image.size, components=4, data=image.convert("RGBA").tobytes())
        image.close()

        if build_mipmaps:
            texture.build_mipmaps()

        return texture
Пример #4
0
def read_tmx(tmx_file: Union[str, Path]) -> pytiled_parser.objects.TileMap:
    """
    Given a .tmx, this will read in a tiled map, and return
    a TiledMap object.

    Given a tsx_file, the map will use it as the tileset.
    If tsx_file is not specified, it will use the tileset specified
    within the tmx_file.

    Important: Tiles must be a "collection" of images.

    Hitboxes can be drawn around tiles in the tileset editor,
    but only polygons are supported.
    (This is a great area for PR's to improve things.)

    :param str tmx_file: String with name of our TMX file

    :returns: Map
    :rtype: TiledMap
    """

    # If we should pull from local resources, replace with proper path
    tmx_file = resolve_resource_path(tmx_file)

    tile_map = pytiled_parser.parse_tile_map(tmx_file)

    return tile_map
def load_spritesheet(file_name: Union[str, Path],
                     sprite_width: int,
                     sprite_height: int,
                     columns: int,
                     count: int,
                     margin: int = 0) -> List[Texture]:
    """

    :param str file_name: Name of the file to that holds the texture.
    :param int sprite_width: Width of the sprites in pixels
    :param int sprite_height: Height of the sprites in pixels
    :param int columns: Number of tiles wide the image is.
    :param int count: Number of tiles in the image.
    :param int margin: Margin between images

    :returns List: List of :class:`Texture` objects.
    """

    texture_list = []

    # If we should pull from local resources, replace with proper path
    file_name = resolve_resource_path(file_name)

    source_image = PIL.Image.open(file_name).convert('RGBA')
    for sprite_no in range(count):
        row = sprite_no // columns
        column = sprite_no % columns
        start_x = (sprite_width + margin) * column
        start_y = (sprite_height + margin) * row
        image = source_image.crop((start_x, start_y, start_x + sprite_width,
                                   start_y + sprite_height))
        texture = Texture(f"{file_name}-{sprite_no}", image)
        texture_list.append(texture)

    return texture_list
Пример #6
0
 def default_style(cls):
     """
     :return: empty style # TODO maybe load the real default style once
     """
     if cls.__default_style is None:
         cls.__default_style = UIStyle.from_file(
             resolve_resource_path(':resources:style/default.yml'))
     return cls.__default_style
Пример #7
0
    def __init__(self, file_name: Union[str, Path], streaming: bool = False):
        self.file_name: str = ""

        file_name = resolve_resource_path(file_name)

        if not Path(file_name).is_file():
            raise FileNotFoundError(
                f"The sound file '{file_name}' is not a file or can't be read."
            )
        self.file_name = str(file_name)

        self.source: Union[media.StaticSource, media.StreamingSource] = media.load(self.file_name, streaming=streaming)

        self.min_distance = 100000000 #setting the players to this allows for 2D panning with 3D audio
Пример #8
0
    def __init__(self, width, height, title):
        super().__init__(width, height, title)
        self.time = 0
        self.program = self.ctx.program(vertex_shader="""
            #version 330

            in vec2 in_vert;
            in vec2 in_uv;
            out vec2 v_uv;

            void main() {
                gl_Position = vec4(in_vert, 0.0, 1.0);
                v_uv = in_uv;
            }
            """,
                                        fragment_shader="""
            #version 330

            uniform sampler2D background;
            uniform float time;

            in vec2 v_uv;
            out vec4 out_color;

            void main() {
                vec2 pos = v_uv * 1.0 - vec2(0.5);
                vec2 uv = v_uv + normalize(pos) + sin(length(pos) * 10 - time);
                out_color = texture(background, uv);
            }
            """)
        self.quad = geometry.screen_rectangle(-1, -1, 2, 2)
        image = Image.open(
            resolve_resource_path(
                ":resources:images/backgrounds/abstract_1.jpg")).convert(
                    "RGBA")
        image = image.transpose(Image.FLIP_TOP_BOTTOM)
        self.texture = self.ctx.texture(image.size,
                                        components=4,
                                        data=image.tobytes())
    def __init__(self, file_name: Union[str, Path], streaming: bool = False):
        """ Create and load the sound. """
        self.file_name: str = ""
        self.wav_file: Union[soloud.WavStream, soloud.Wav]

        self.voice_handle = None  # needed for volume control

        if not _audiolib:
            return

        # If we should pull from local resources, replace with proper path
        file_name = resolve_resource_path(file_name)

        if not Path(file_name).is_file():
            raise FileNotFoundError(
                f"The sound file '{file_name}' is not a file or can't be read")
        self.file_name = str(file_name)

        if streaming:
            self.wav_file = soloud.WavStream()
        else:
            self.wav_file = soloud.Wav()
        self.wav_file.load(self.file_name)
def load_texture(file_name: Union[str, Path],
                 x: float = 0,
                 y: float = 0,
                 width: float = 0,
                 height: float = 0,
                 flipped_horizontally: bool = False,
                 flipped_vertically: bool = False,
                 flipped_diagonally: bool = False,
                 can_cache: bool = True,
                 mirrored=None,
                 hit_box_algorithm="Simple",
                 hit_box_detail: float = 4.5) -> Texture:
    """
    Load an image from disk and create a texture.

    Note: If the code is to load only part of the image, the given `x`, `y`
    coordinates will start with the origin `(0, 0)` in the upper left of the
    image. When drawing, Arcade uses `(0, 0)` in the lower left corner.
    Be careful with this reversal.

    For a longer explanation of why computers sometimes start in the upper
    left, see:
    http://programarcadegames.com/index.php?chapter=introduction_to_graphics&lang=en#section_5

    :param str file_name: Name of the file to that holds the texture.
    :param float x: X position of the crop area of the texture.
    :param float y: Y position of the crop area of the texture.
    :param float width: Width of the crop area of the texture.
    :param float height: Height of the crop area of the texture.
    :param bool flipped_horizontally: Mirror the sprite image. Flip left/right across vertical axis.
    :param bool flipped_vertically: Flip the image up/down across the horizontal axis.
    :param bool flipped_diagonally: Transpose the image, flip it across the diagonal.
    :param bool can_cache: If a texture has already been loaded, load_texture will return the same texture in order \
    to save time. Sometimes this is not desirable, as resizing a cached texture will cause all other textures to \
    resize with it. Setting can_cache to false will prevent this issue at the experience of additional resources.
    :param bool mirrored: Deprecated.
    :param str hit_box_algorithm: One of 'None', 'Simple' or 'Detailed'. \
    Defaults to 'Simple'. Use 'Simple' for the :data:`PhysicsEngineSimple`, \
    :data:`PhysicsEnginePlatformer` \
    and 'Detailed' for the :data:`PymunkPhysicsEngine`.

        .. figure:: images/hit_box_algorithm_none.png
           :width: 40%

           hit_box_algorithm = "None"

        .. figure:: images/hit_box_algorithm_simple.png
           :width: 55%

           hit_box_algorithm = "Simple"

        .. figure:: images/hit_box_algorithm_detailed.png
           :width: 75%

           hit_box_algorithm = "Detailed"
    :param float hit_box_detail: Float, defaults to 4.5. Used with 'Detailed' to hit box

    :returns: New :class:`Texture` object.

    :raises: ValueError
    """

    if mirrored is not None:
        from warnings import warn
        warn(
            "In load_texture, the 'mirrored' parameter is deprecated. Use 'flipped_horizontally' instead.",
            DeprecationWarning)
        flipped_horizontally = mirrored

    # See if we already loaded this texture, and we can just use a cached version.
    cache_name = "{}-{}-{}-{}-{}-{}-{}-{}-{}".format(
        file_name, x, y, width, height, flipped_horizontally,
        flipped_vertically, flipped_diagonally, hit_box_algorithm)
    if can_cache and cache_name in load_texture.texture_cache:  # type: ignore # dynamic attribute on function obj
        return load_texture.texture_cache[
            cache_name]  # type: ignore # dynamic attribute on function obj

    # See if we already loaded this texture file, and we can just use a cached version.
    cache_file_name = f"{file_name}"
    if cache_file_name in load_texture.texture_cache:  # type: ignore # dynamic attribute on function obj
        texture = load_texture.texture_cache[
            cache_file_name]  # type: ignore # dynamic attribute on function obj
        source_image = texture.image
    else:
        # If we should pull from local resources, replace with proper path
        file_name = resolve_resource_path(file_name)

        source_image = PIL.Image.open(file_name).convert('RGBA')
        result = Texture(cache_file_name,
                         source_image,
                         hit_box_algorithm=hit_box_algorithm,
                         hit_box_detail=hit_box_detail)
        load_texture.texture_cache[
            cache_file_name] = result  # type: ignore # dynamic attribute on function obj

    source_image_width, source_image_height = source_image.size

    if x != 0 or y != 0 or width != 0 or height != 0:
        if x > source_image_width:
            raise ValueError("Can't load texture starting at an x of {} "
                             "when the image is only {} across.".format(
                                 x, source_image_width))
        if y > source_image_height:
            raise ValueError("Can't load texture starting at an y of {} "
                             "when the image is only {} high.".format(
                                 y, source_image_height))
        if x + width > source_image_width:
            raise ValueError("Can't load texture ending at an x of {} "
                             "when the image is only {} wide.".format(
                                 x + width, source_image_width))
        if y + height > source_image_height:
            raise ValueError("Can't load texture ending at an y of {} "
                             "when the image is only {} high.".format(
                                 y + height, source_image_height))

        image = source_image.crop((x, y, x + width, y + height))
    else:
        image = source_image

    # image = _trim_image(image)
    if flipped_diagonally:
        image = image.transpose(PIL.Image.TRANSPOSE)

    if flipped_horizontally:
        image = image.transpose(PIL.Image.FLIP_LEFT_RIGHT)

    if flipped_vertically:
        image = image.transpose(PIL.Image.FLIP_TOP_BOTTOM)

    result = Texture(cache_name,
                     image,
                     hit_box_algorithm=hit_box_algorithm,
                     hit_box_detail=hit_box_detail)
    load_texture.texture_cache[
        cache_name] = result  # type: ignore # dynamic attribute on function obj
    return result
def load_textures(file_name: Union[str, Path],
                  image_location_list: RectList,
                  mirrored: bool = False,
                  flipped: bool = False) -> List[Texture]:
    """
    Load a set of textures from a single image file.

    Note: If the code is to load only part of the image, the given `x`, `y`
    coordinates will start with the origin `(0, 0)` in the upper left of the
    image. When drawing, Arcade uses `(0, 0)` in the lower left corner.
    Be careful with this reversal.

    For a longer explanation of why computers sometimes start in the upper
    left, see:
    http://programarcadegames.com/index.php?chapter=introduction_to_graphics&lang=en#section_5

    :param str file_name: Name of the file.
    :param List image_location_list: List of image sub-locations. Each rectangle should be
           a `List` of four floats: `[x, y, width, height]`.
    :param bool mirrored: If set to `True`, the image is mirrored left to right.
    :param bool flipped: If set to `True`, the image is flipped upside down.

    :returns: List of :class:`Texture`'s.

    :raises: ValueError
    """
    # See if we already loaded this texture file, and we can just use a cached version.
    cache_file_name = "{}".format(file_name)
    if cache_file_name in load_texture.texture_cache:  # type: ignore # dynamic attribute on function obj
        texture = load_texture.texture_cache[
            cache_file_name]  # type: ignore # dynamic attribute on function obj
        source_image = texture.image
    else:
        file_name = resolve_resource_path(file_name)

        source_image = PIL.Image.open(file_name)
        result = Texture(cache_file_name, source_image)
        load_texture.texture_cache[
            cache_file_name] = result  # type: ignore # dynamic attribute on function obj

    source_image_width, source_image_height = source_image.size
    texture_info_list = []
    for image_location in image_location_list:
        x, y, width, height = image_location

        if width <= 0:
            raise ValueError(
                "Texture has a width of {}, must be > 0.".format(width))
        if x > source_image_width:
            raise ValueError("Can't load texture starting at an x of {} "
                             "when the image is only {} across.".format(
                                 x, source_image_width))
        if y > source_image_height:
            raise ValueError("Can't load texture starting at an y of {} "
                             "when the image is only {} high.".format(
                                 y, source_image_height))
        if x + width > source_image_width:
            raise ValueError("Can't load texture ending at an x of {} "
                             "when the image is only {} wide.".format(
                                 x + width, source_image_width))
        if y + height > source_image_height:
            raise ValueError("Can't load texture ending at an y of {} "
                             "when the image is only {} high.".format(
                                 y + height, source_image_height))

        # See if we already loaded this texture, and we can just use a cached version.
        cache_name = "{}{}{}{}{}{}{}".format(file_name, x, y, width, height,
                                             flipped, mirrored)
        if cache_name in load_texture.texture_cache:  # type: ignore # dynamic attribute on function obj
            result = load_texture.texture_cache[
                cache_name]  # type: ignore # dynamic attribute on function obj
        else:
            image = source_image.crop((x, y, x + width, y + height))
            # image = _trim_image(image)

            if mirrored:
                image = PIL.ImageOps.mirror(image)

            if flipped:
                image = PIL.ImageOps.flip(image)
            result = Texture(cache_name, image)
            load_texture.texture_cache[
                cache_name] = result  # type: ignore # dynamic attribute on function obj
        texture_info_list.append(result)

    return texture_info_list