Beispiel #1
0
    # update texture
    curtime = pg.time.get_ticks()
    if curtime >= next_tex_update:
        for x_ in range(streamtex.width // 4):
            for y_ in range(streamtex.height // 4):
                newcol = (
                    random.randint(0, 255),
                    random.randint(0, 255),
                    random.randint(0, 255),
                    255,
                )
                area = (4 * x_, 4 * y_, 4, 4)
                surf.fill(newcol, area)
        streamtex.update(surf)
        next_tex_update = curtime + tex_update_interval
    streamtex.draw(dstrect=pg.Rect(64, 128, 64, 64))

    tex.draw(dstrect=(x, y))

    # TODO: should these be?
    # - line instead of draw_line
    # - point instead of draw_point
    # - rect(rect, width=1)->draw 1 pixel, instead of draw_rect
    # - rect(rect, width=0)->filled ? , instead of fill_rect
    #
    # TODO: should these work with pg.draw.line(renderer, ...) functions?
    renderer.draw_color = (255, 255, 255, 255)
    renderer.draw_line((0, 0), (64, 64))
    renderer.draw_line((64, 64), (128, 0))
    renderer.draw_point((72, 32))
    renderer.draw_rect(pg.Rect(0, 64, 64, 64))
Beispiel #2
0
def sprites():
    pg.init()
    clock = pg.time.Clock()
    window = Window("Renderpyg Example", size=WINDOW_RESOLUTION)
    renderer = Renderer(window, vsync=True)
    """ 
	We will draw into a buffer texture to allow easy resolution changes
	It will also make it easier to apply screen transitions and similar effects later

	When using pygame._sdl2.video you do not call pygame.display.setmode()
	Therefore calling surface.convert() or surface.convert_alpha() will throw an error
	When you create a Texture that needs alpha blending you must set its blend mode
	Alpha blending will be set automatically when loading from an image with transparency, such as PNG

	Remember to use the buffer size instead of the window size when drawing onto the offscreen buffer
	This will allow you to scale the screen to any window or fullscreen desktop size
	"""
    buffer = Texture(renderer, RENDER_RESOLUTION, target=True)
    buffer.blend_mode = 1
    screensize = buffer.get_rect()
    """ 
	You can set fullscreen when creating the window by using Window(title, size, desktop_fullscreen=True)
	I prefer creating a window before going to fullscreen to avoid strange window placement that occurs
	if you exit fullscreen later on.
	"""
    FULLSCREEN = False
    if FULLSCREEN:
        window.set_fullscreen(True)
    """
	Font features in pygame are design for blitting to a surface, not for GPU rendering
	It is possible to create a streaming texture and then using texture.update() to update the texture
	from a pygame surface, but accessing GPU memory is slow and this should be done sparingly.

	Therefore I created a simple TextureFont class. We will use the animation feature of this class
	for a little extra fun. We will also create some sprites and let them animate too.

	Also, for this example we use a Character class to move and rotate individual characters across
	the screen. This is very similar to how you will handle sprites later.
	"""
    tfont = TextureFont(renderer, FONT, FONT_SIZE)
    sprite = Sprite((renderer, EXAMPLE_DATA + 'aliens.png'),
                    7,
                    8,
                    by_count=True)
    group = pg.sprite.Group()
    animations = [
        keyrange(0, 7, 200),
        keyrange(7, 14, 200),
        keyrange(14, 21, 200),
        keyrange(28, 35, 200)
    ]

    for _ in range(SPRITE_COUNT):
        spr = Sprite(sprite.images)
        spr.set_pos(randrange(0, RENDER_RESOLUTION[0]),
                    randrange(0, RENDER_RESOLUTION[1]))
        spr.set_animation(random.choice(animations), -1)
        spr.velocity = pg.Vector2(randrange(-10, 11), randrange(-10, 11))
        if randrange(10) < 2:
            spr.rotation = randrange(-10, 11)
        group.add(spr)
    """ 
	Here starts a simple game loop
	Press SPACE to toggle between a large window, a small window, and fullscreen
	Press ENTER to add more characters to the screen

	At the beginning of each frame we must set the renderer target to our buffer Texture
	All the following draw calls will be drawn to the buffer instead of the screen
	After all of our drawing, we reset the target and draw the buffer onto the screen
	"""
    timer = pg.time.get_ticks()
    delta = 0
    running = True
    while running:
        renderer.target = buffer
        for event in pg.event.get():
            if event.type == pg.QUIT:
                running = False
            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_ESCAPE:
                    running = False
                elif event.key == pg.K_SPACE:
                    if FULLSCREEN:
                        FULLSCREEN = False
                        window.size = WINDOW_RESOLUTION
                        window.set_windowed()
                    elif window.size == WINDOW_RESOLUTION:
                        window.size = SMALL_RESOLUTION
                    else:
                        FULLSCREEN = True
                        window.size = WINDOW_RESOLUTION
                        window.set_fullscreen(True)

        #Must set the draw color before clearing the scren or drawing lines and rectt

        renderer.draw_color = (0, 0, 0, 255)
        renderer.clear()
        """
		Draw the background image if available. 
		By default Texture.draw() will fill the renderer unless you supply a destination Rect
		texture.draw( dstrect=Rect(x, y, width, height) )
		"""
        group.update(delta)
        group.draw()
        tfont.animate(**FONT_PARAMS)

        # Setting renderer.target = None will make following draw calls render to the underlying window
        # Since we don't provide a dstrect it will fill the renderer

        renderer.target = None
        buffer.draw()
        renderer.present(
        )  # all draw calls occur and the screen is updated here
        delta = clock.tick(FRAMES_PER_SECOND)
Beispiel #3
0
def scale_tilemap(tilemap, camera=(0, 0), scale=1, **kwargs):
    '''
	WIP smooth scaling tilemap renderer
	Still haven't gotten this working properly
	'''
    return
    global buffer
    global printfo
    renderer = tilemap.images[1].texture.renderer
    old_viewport = renderer.get_viewport()
    old_target = renderer.target
    rend_width, rend_height = renderer.target.get_rect().size if \
      renderer.target else old_viewport.size

    if not buffer:
        renderer.set_viewport(None)
        size = renderer.get_viewport().size
        buffer = Texture(renderer, size, target=True)
        buffer.blend_mode = 1
    renderer.target = buffer
    renderer.clear()

    rendered_rect = renderer.get_viewport()
    if scale > 1:
        wanted_rect = scale_rect(rendered_rect, 1 / scale)
        src_rect = wanted_rect
        scale = 1
    elif scale < 1:
        pass

    elif scale < 1:
        actual_scale = max(scale, .5)
        scale = 0.5
        rect_scale = scale / actual_scale
        wanted_rect = scale_rect(rendered_rect, rect_scale)
        src_rect = wanted_rect
        printfo = (f'actual={actual_scale}, set={scale}, rect={rect_scale}, '
                   'rect={src_rect}')

    elif False:
        tiles_wide = math.ceil(rend_width / (scale * tilemap.tilewidth))
        adjusted_scale = (rend_width / tilemap.tilewidth) / tiles_wide
        buffer_scale = 1 - (scale - adjusted_scale)
        printfo = (f'base= {rend_width/tilemap.tilewidth}, tiles wide='
                   '{tiles_wide}, new_scale={buffer_scale}')
        wanted_rect = scale_rect(rendered_rect, buffer_scale)
        src_rect = wanted_rect
        src_rect.center = rendered_rect.center
        scale = adjusted_scale
    else:
        src_rect = rendered_rect

    if True:  # center
        cam_x = (camera.x * scale) - (rend_width / 2)
        cam_y = (camera.y * scale) - (rend_height / 2)
    else:
        cam_x = camera.x * scale
        cam_y = camera.y * scale

    cell_count = len(tilemap.images)
    tile_w = int(tilemap.tilewidth * scale)
    tile_h = int(tilemap.tileheight * scale)
    cells_wide = rend_width // tile_w + 2
    cells_high = rend_height // tile_h + 2

    start_cellx, offset_x = divmod(int(cam_x), tile_w)
    start_celly, offset_y = divmod(int(cam_y), tile_h)
    offset_x = 0
    offset_y = 0

    percent = offset_x / tile_w

    if start_cellx < 0:  # Handle negative values
        offset_x += start_cellx * tile_w
        start_cellx = 0
    if start_celly < 0:
        offset_y += start_celly * tile_h
        start_celly = 0

    dest_rect = pg.Rect(0, 0, tile_w, tile_h)
    layer = tilemap.layers[0].data
    '''
	Render Tilemap
	'''
    for row in layer[start_celly:start_celly + cells_high]:
        for frame in row[start_cellx:start_cellx + cells_wide]:
            if frame > 0:
                tilemap.images[frame].draw(dstrect=dest_rect)
            dest_rect.x += tile_w
        dest_rect.y += tile_h
        dest_rect.x = 0

    renderer.target = old_target
    buffer.draw(srcrect=src_rect)
    '''
	Cleanup
	'''
    return cam_x, cam_y, scale
Beispiel #4
0
    renderer.clear()

    # update texture
    curtime = get_ticks()
    if curtime >= next_tex_update:
        for x_ in range(streamtex.width // 4):
            for y_ in range(streamtex.height // 4):
                newcol = random.randint(0, 255), \
                         random.randint(0, 255), \
                         random.randint(0, 255), \
                         255
                area = (4 * x_, 4 * y_, 4, 4)
                surf.fill(newcol, area)
        streamtex.update(surf)
        next_tex_update = curtime + tex_update_interval
    streamtex.draw(dstrect=pygame.Rect(64, 128, 64, 64))

    tex.draw(dstrect=(x, y))

    #TODO: should these be?
    # - line instead of draw_line
    # - point instead of draw_point
    # - rect(rect, width=1)->draw 1 pixel, instead of draw_rect
    # - rect(rect, width=0)->filled ? , instead of fill_rect
    #
    # TODO: should these work with pygame.draw.line(renderer, ...) functions?
    renderer.draw_color = (255, 255, 255, 255)
    renderer.draw_line((0, 0), (64, 64))
    renderer.draw_line((64, 64), (128, 0))
    renderer.draw_point((72, 32))
    renderer.draw_rect(pygame.Rect(0, 64, 64, 64))
Beispiel #5
0
def render_tilemap(tilemap, camera=(0, 0), scale=1, **kwargs):
    '''
	Draw pytmx or inbuilt tilemap onto pygame GPU renderer

	:param tilemap: pytmx or internal tilemap class
	:param camera: pg.Vector2 for top left camera location
	:param scale: float scale value defaults to 1.0
	:param center: pg.Vector2 to set center camera location
			True to adjust camera for center
			Overides camera
	:param srcrect: area to render in world coordinates overides scale
			Ignores height to maintain aspect ratio
	:param dstrect: screen area to render into
			defaults to entire renderer area
	:param smooth: for smoother scaling transition but less accurate
	:param clamp: True to adjust camera to fit world coordinates
	:rvalue (camx, camy, scale): for adjusting other images

	TODO:
		impliment smoothing
	'''
    '''
	Setup renderer and viewport
	'''
    global buffer
    renderer = tilemap.images[1].texture.renderer
    old_viewport = renderer.get_viewport()
    old_target = renderer.target
    rend_width, rend_height = renderer.target.get_rect().size if\
      renderer.target else old_viewport.size
    '''
	Parse options
	'''
    smooth = kwargs.get('smooth', False)
    clamp = kwargs.get('clamp', False)
    cam_x = int(camera.x)
    cam_y = int(camera.y)

    if smooth and scale != 1:
        if not buffer:
            renderer.set_viewport(None)
            size = renderer.get_viewport().size
            buffer = Texture(renderer, size, target=True)
            buffer.blend_mode = 1
        renderer.target = buffer
        renderer.clear()

    dstrect = kwargs.get('dstrect', None)
    try:
        if dstrect:
            if not hasattr(dstrect, 'width'):
                dstrect = pg.Rect(*dstrect)
            renderer.set_viewport(dstrect)
            rend_width = dstrect.width
            rend_height = dstrect.height
    except:
        raise ValueError(
            'render_tilemap() cannot parse "{}" as dest_rect'.format(dstrect))

    srcrect = kwargs.get('srcrect', None)
    try:
        if hasattr(srcrect, 'width'):
            renderer.set_viewport(srcrect)
            camera = srcrect.pos
            scale = rend_width / srcrect.width
            center = False
        elif srcrect:
            srcrect = pg.Rect(srcrect)
    except:
        raise ValueError(
            'render_tilemap() cannot parse "{}" as src_rect'.format(dstrect))

    center = kwargs.get('center', False)
    try:
        if center and center != True:
            cam_x = int(center[0])
            cam_y = int(center[1])
            center = True
    except:
        raise ValueError(
            'render_tilemap() cannot parse "{}" as center pos'.format(center))

    if center:
        cam_x = (cam_x * scale) - (rend_width / 2)
        cam_y = (cam_y * scale) - (rend_height / 2)
    else:
        cam_x = cam_x * scale
        cam_y = cam_y * scale
    '''
	Prepare to render the tilemap
	'''
    cell_count = len(tilemap.images)
    tile_w = int(tilemap.tilewidth * scale)
    tile_h = int(tilemap.tileheight * scale)
    cells_wide = rend_width // tile_w + 2
    cells_high = rend_height // tile_h + 2

    if clamp:
        cam_x = min(max(0, cam_x), tile_w * tilemap.width - rend_width)
        cam_y = min(max(0, cam_y), tile_h * tilemap.height - rend_height)

    start_cellx, offset_x = divmod(int(cam_x), tile_w)
    start_celly, offset_y = divmod(int(cam_y), tile_h)

    if start_cellx < 0:  # Handle negative values
        offset_x += start_cellx * tile_w
        start_cellx = 0
    if start_celly < 0:
        offset_y += start_celly * tile_h
        start_celly = 0

    dest_rect = pg.Rect(-offset_x, -offset_y, tile_w, tile_h)
    layer = tilemap.layers[0].data
    '''
	Render Tilemap
	'''
    for row in layer[start_celly:start_celly + cells_high]:
        for frame in row[start_cellx:start_cellx + cells_wide]:
            if frame > 0:
                tilemap.images[frame].draw(dstrect=dest_rect)
            dest_rect.x += tile_w
        dest_rect.y += tile_h
        dest_rect.x = -offset_x

    if smooth and scale != 1:
        renderer.target = old_target
        dest_rect.x = 0
        dest_rect.y = 0
        dest_rect.width = (tilemap.tilewidth * scale) * (rend_width //
                                                         tilemap.tilewidth)
        dest_rect.height = (tilemap.tileheight * scale) * (rend_height //
                                                           tilemap.tileheight)
        global printfo
        printfo = f'{dest_rect}, {tilemap.tilewidth*scale}, {cells_wide-2}'
        buffer.draw(srcrect=dest_rect)
    '''
	Cleanup
	'''
    return cam_x, cam_y, scale