def compute_rectangles(self, texture, game_object, camera): flags = sdl2.stdinc.Uint32() access = ctypes.c_int() img_w = ctypes.c_int() img_h = ctypes.c_int() sdl_call( SDL_QueryTexture, texture, ctypes.byref(flags), ctypes.byref(access), ctypes.byref(img_w), ctypes.byref(img_h), _check_error=lambda rv: rv < 0 ) rect = getattr(game_object, 'rect', None) if rect: src_rect = SDL_Rect(*rect) win_w = rect[2] * game_object.size win_h = rect[3] * game_object.size else: src_rect = SDL_Rect(x=0, y=0, w=img_w, h=img_h) if hasattr(game_object, 'width'): obj_w = game_object.width obj_h = game_object.height else: obj_w, obj_h = game_object.size win_w, win_h = self.target_resolution(img_w.value, img_h.value, obj_w, obj_h, camera.pixel_ratio) center = camera.translate_point_to_screen(game_object.position) dest_rect = SDL_Rect( x=int(center.x - win_w / 2), y=int(center.y - win_h / 2), w=int(win_w), h=int(win_h), ) return src_rect, dest_rect, ctypes.c_double(-game_object.rotation)
def _draw_shape(self, renderer, rgb, **_): sdl_call(SDL_SetRenderDrawColor, renderer, *rgb, 255, _check_error=lambda rv: rv < 0) sdl_call(SDL_RenderFillRect, renderer, None, _check_error=lambda rv: rv < 0)
def __init__(self, red: int, green: int, blue: int): color = red, green, blue self._surface = _create_surface(color) renderer = sdl_call(SDL_CreateSoftwareRenderer, self._surface, _check_error=lambda rv: not rv) try: self._draw_shape(renderer, rgb=color) finally: sdl_call(SDL_DestroyRenderer, renderer)
def _draw_shape(self, renderer, rgb, **_): half = int(DEFAULT_SPRITE_SIZE / 2) sdl_call( filledCircleRGBA, renderer, half, half, # Center half, # Radius *rgb, 255, _check_error=lambda rv: rv < 0)
def render_background(self, scene): bg = scene.background_color sdl_call(SDL_SetRenderDrawColor, self.renderer, bg[0], bg[1], bg[2], 255, _check_error=lambda rv: rv < 0) sdl_call(SDL_RenderClear, self.renderer, _check_error=lambda rv: rv < 0)
def _draw_shape(self, renderer, rgb, **_): sdl_call(filledTrigonRGBA, renderer, 0, DEFAULT_SPRITE_SIZE, int(DEFAULT_SPRITE_SIZE / 2), 0, DEFAULT_SPRITE_SIZE, DEFAULT_SPRITE_SIZE, *rgb, 255, _check_error=lambda rv: rv < 0)
def _background(self): surface = _create_surface(self.color) renderer = sdl_call(SDL_CreateSoftwareRenderer, surface, _check_error=lambda rv: not rv) try: self._draw_shape(renderer, rgb=self.color) finally: sdl_call(SDL_DestroyRenderer, renderer) return surface
def background_parse(self, data): file = rw_from_object(io.BytesIO(data)) # ^^^^ is a pure-python emulation, does not need cleanup. surface = img_call(IMG_Load_RW, file, False, _check_error=lambda rv: not rv) sdl_call(SDL_SetSurfaceBlendMode, surface, SDL_BLENDMODE_BLEND, _check_error=lambda rv: rv < 0) return surface
def prepare_resource(self, game_object): """ Get the SDL Texture for an object. """ if not self._object_has_dimension(game_object): return None if not hasattr(game_object, '__image__'): return image = game_object.__image__() if image is flags.DoNotRender or image is None: return None surface = image.load() try: return 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
def __enter__(self): super().__enter__() img_call(IMG_Init, IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF) ttf_call(TTF_Init, _check_error=lambda rv: rv == -1) self.window = ctypes.POINTER(SDL_Window)() self.renderer = ctypes.POINTER(SDL_Renderer)() sdl_call( SDL_CreateWindowAndRenderer, self.resolution[0], # Width self.resolution[1], # Height 0, # Flags # SDL_WINDOW_ALLOW_HIGHDPI - Allow the renderer to work in HiDPI natively ctypes.byref(self.window), ctypes.byref(self.renderer), _check_error=lambda rv: rv < 0) # NOTE: It looks like SDL_RENDERER_PRESENTVSYNC will cause SDL_RenderPresent() to block? sdl_call(SDL_SetWindowTitle, self.window, self.window_title.encode('utf-8'))
def on_render(self, render_event, signal): camera = render_event.scene.main_camera self.render_background(render_event.scene) for game_object in render_event.scene.sprite_layers(): texture = self.prepare_resource(game_object) if texture is None: continue src_rect, dest_rect, angle = self.compute_rectangles( texture.inner, game_object, camera ) flip = getattr(game_object, 'flip', SDL_FLIP_NONE) sdl_call( SDL_RenderCopyEx, self.renderer, texture.inner, ctypes.byref(src_rect), ctypes.byref(dest_rect), angle, None, flip, _check_error=lambda rv: rv < 0 ) sdl_call(SDL_RenderPresent, self.renderer)
def _create_surface(color): """ Creates a surface for assets and sets the color key. """ surface = sdl_call(SDL_CreateRGBSurface, 0, DEFAULT_SPRITE_SIZE, DEFAULT_SPRITE_SIZE, 32, 0, 0, 0, 0, _check_error=lambda rv: not rv) color_key = BLACK if color != BLACK else MAGENTA color = sdl2.ext.Color(*color_key) sdl_call(SDL_SetColorKey, surface, True, sdl2.ext.prepare_color(color, surface.contents), _check_error=lambda rv: rv < 0) sdl2.ext.fill(surface.contents, color) return surface
def prepare_resource(self, game_object): """ Get the SDL Texture for an object. """ if not self._object_has_dimension(game_object): return None if not hasattr(game_object, '__image__'): return image = game_object.__image__() if image is None: return None surface = image.load() try: 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 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 prepare_resource(self, game_object): texture = super().prepare_resource(game_object) if texture: opacity = getattr(game_object, 'opacity', 255) opacity_mode = getattr(game_object, 'opacity_mode', 'blend') color = getattr(game_object, 'color', (255, 255, 255)) if True: # opacity != self.last_opacity: sdl_call(SDL_SetTextureAlphaMod, texture.inner, opacity, _check_error=lambda rv: rv < 0) self.last_opacity = opacity if True: #opacity_mode != self.last_opacity_mode: self.last_opacity_mode = opacity_mode if opacity_mode == 'add': sdl_call(SDL_SetTextureBlendMode, texture.inner, SDL_BLENDMODE_ADD, _check_error=lambda rv: rv < 0) elif opacity_mode == 'blend': sdl_call(SDL_SetTextureBlendMode, texture.inner, SDL_BLENDMODE_BLEND, _check_error=lambda rv: rv < 0) else: raise ValueError( f"Support modes for translucent sprites are 'add' or 'blend', not '{opacity_mode}'." ) if True: # color != self.last_color: sdl_call(SDL_SetTextureColorMod, texture.inner, color[0], color[1], color[2], _check_error=lambda rv: rv < 0) self.last_color = color return texture
def file_missing(self): width = height = 70 # Pixels, arbitrary surface = sdl_call(SDL_CreateRGBSurface, 0, width, height, 32, 0, 0, 0, 0, _check_error=lambda rv: not rv) rand = random.Random(str(self.name)) r = rand.randint(65, 255) g = rand.randint(65, 255) b = rand.randint(65, 255) color = sdl2.ext.Color(r, g, b) sdl2.ext.fill(surface.contents, color) return surface
def __exit__(self, *exc): sdl_call(SDL_DestroyRenderer, self.renderer) sdl_call(SDL_DestroyWindow, self.window) ttf_call(TTF_Quit) img_call(IMG_Quit) super().__exit__(*exc)