Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply alpha blend modes and coloration to textures based on sprite data. #474

Merged
merged 2 commits into from
May 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions ppb/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,34 @@ class DoNotRender(Flag):
"""
Inform the renderer to ignore this object.
"""


class BlendMode(Flag, abstract=True):
"""
A flag indicating a blend mode, changing how translucent sprites are drawn
over top of other sprites.
"""


class BlendModeAdd(BlendMode):
"""
Indicate a sprite, if translucent, should be rendered in ADD mode.
"""


class BlendModeBlend(BlendMode):
"""
Indicate a sprite, if translucent, should be rendered in BLEND mode.
"""


class BlendModeMod(BlendMode):
"""
Indicate a sprite, if translucent, should be rendered in MOD mode.
"""


class BlendModeNone(BlendMode):
"""
Indicate a sprite, if translucent, should be rendered in NONE mode.
"""
3 changes: 3 additions & 0 deletions ppb/sprites.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class RenderableMixin:
#: (:py:class:`ppb.Image`): The image asset
image = None # TODO: Type hint appropriately
size = 1
blend_mode: 'ppb.flags.BlendMode' # One of four blending modes
opacity: int # An opacity value from 0-255
color: 'ppb.utils.Color' # A 3-tuple color with values 0-255

def __image__(self):
"""
Expand Down
40 changes: 38 additions & 2 deletions ppb/systems/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import io
import logging
import random
from typing import Tuple

import sdl2
import sdl2.ext
Expand All @@ -25,6 +26,13 @@
SDL_QueryTexture, # https://wiki.libsdl.org/SDL_QueryTexture
SDL_RenderCopyEx, # https://wiki.libsdl.org/SDL_RenderCopyEx
SDL_CreateRGBSurface, # https://wiki.libsdl.org/SDL_CreateRGBSurface
SDL_BLENDMODE_ADD,
SDL_BLENDMODE_BLEND,
SDL_BLENDMODE_MOD,
SDL_BLENDMODE_NONE,
SDL_SetTextureAlphaMod,
SDL_SetTextureBlendMode,
SDL_SetTextureColorMod,
)

from sdl2.sdlimage import (
Expand Down Expand Up @@ -52,6 +60,13 @@

DEFAULT_RESOLUTION = 800, 600

OPACITY_MODES = {
flags.BlendModeAdd: SDL_BLENDMODE_ADD,
flags.BlendModeBlend: SDL_BLENDMODE_BLEND,
flags.BlendModeMod: SDL_BLENDMODE_MOD,
flags.BlendModeNone: SDL_BLENDMODE_NONE,
}


# TODO: Move Image out of the renderer so sprites can type hint appropriately.
class Image(assets.Asset):
Expand Down Expand Up @@ -233,14 +248,35 @@ def prepare_resource(self, game_object):

surface = image.load()
try:
return self._texture_cache[surface]
texture = self._texture_cache[surface]
except KeyError:
texture = SmartPointer(sdl_call(
SDL_CreateTextureFromSurface, self.renderer, surface,
_check_error=lambda rv: not rv
), SDL_DestroyTexture)
self._texture_cache[surface] = texture
return texture

opacity = getattr(game_object, 'opacity', 255)
opacity_mode = getattr(game_object, 'opacity_mode', flags.BlendModeBlend)
opacity_mode = OPACITY_MODES[opacity_mode]
tint = getattr(game_object, 'tint', (255, 255, 255))

sdl_call(
SDL_SetTextureAlphaMod, texture.inner, opacity,
_check_error=lambda rv: rv < 0
)

sdl_call(
SDL_SetTextureBlendMode, texture.inner, opacity_mode,
_check_error=lambda rv: rv < 0
)

sdl_call(
SDL_SetTextureColorMod, texture.inner, tint[0], tint[1], tint[2],
_check_error=lambda rv: rv < 0
)

return texture

def compute_rectangles(self, texture, game_object, camera):
flags = sdl2.stdinc.Uint32()
Expand Down
5 changes: 4 additions & 1 deletion ppb/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
import re
import sys
from time import perf_counter
import typing

__all__ = 'LoggingMixin', 'camel_to_snake', 'get_time'
__all__ = 'LoggingMixin', 'camel_to_snake', 'get_time', 'Color'


Color = typing.Tuple[int, int, int]

# Dictionary mapping file names -> module names
_module_file_index = {}

Expand Down