view pytouhou/ui/sdl/gamerenderer.py @ 533:de778a80820a

Optimise Clock a bit more.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Mon, 10 Feb 2014 18:03:50 +0100
parents dacdcca59b66
children b895ed2de71f
line wrap: on
line source

# -*- encoding: utf-8 -*-
##
## Copyright (C) 2011 Thibaut Girka <thib@sitedethib.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 3 only.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##

from itertools import chain

from pytouhou.lib.sdl import Rect

from pytouhou.utils.helpers import get_logger
logger = get_logger(__name__)


class GameRenderer(object):
    def __init__(self, resource_loader, window):
        self.window = window
        self.texture_manager = TextureManager(resource_loader, self.window.win)


    def load_textures(self, anms):
        self.texture_manager.load(anms)


    def load_background(self, background):
        if background is not None:
            logger.error('Background rendering unavailable in the SDL backend.')


    def start(self, common):
        pass


    def render(self, game):
        self.render_game(game)
        self.render_text(game.texts)
        self.render_interface(game.interface, game.boss)


    def render_game(self, game):
        x, y = game.interface.game_pos
        self.window.win.render_set_viewport(Rect(x, y, game.width, game.height))
        self.window.win.render_set_clip_rect(Rect(x, -y, game.width, game.height))

        if game is not None:
            if game.spellcard_effect is not None:
                self.render_elements([game.spellcard_effect])
            else:
                self.window.win.render_clear()

            self.render_elements([enemy for enemy in game.enemies if enemy.visible])
            self.render_elements(game.effects)
            self.render_elements(chain(game.players_bullets,
                                       game.lasers_sprites(),
                                       game.players,
                                       game.msg_sprites()))
            self.render_elements(chain(game.bullets, game.lasers,
                                       game.cancelled_bullets, game.items,
                                       game.labels))


    def render_interface(self, interface, boss):
        interface.labels['framerate'].set_text('%.2ffps' % self.window.get_fps())

        self.window.win.render_set_viewport(Rect(0, 0, interface.width, interface.height))
        self.window.win.render_set_clip_rect(Rect(0, 0, interface.width, interface.height))

        items = [item for item in interface.items if item.anmrunner and item.anmrunner.running]
        labels = interface.labels.values()

        if items:
            # Redraw all the interface
            self.render_elements(items)
        else:
            # Redraw only changed labels
            labels = [label for label in labels if label.changed]

        self.render_elements(interface.level_start)

        if boss:
            self.render_elements(interface.boss_items)

        self.render_elements(labels)
        for label in labels:
            label.changed = False


    def render_elements(self, elements):
        nb_vertices = 0

        objects = chain(*[element.objects for element in elements])
        for element in objects:
            if nb_vertices >= MAX_ELEMENTS - 4:
                break

            sprite = element.sprite
            if sprite and sprite.visible:
                ox, oy = element.x, element.y
                data = get_sprite_rendering_data(sprite)

                #XXX
                texture_width = 256
                texture_height = 256

                source = Rect(data.left * texture_width,
                              data.bottom * texture_height,
                              (data.right - data.left) * texture_width,
                              (data.top - data.bottom) * texture_height)

                dest = Rect(ox + data.x, oy + data.y, data.width, data.height)

                texture = sprite.anm.texture
                texture.set_color_mod(data.r, data.g, data.b)
                texture.set_alpha_mod(data.a)
                texture.set_blend_mode(2 if data.blendfunc else 1)

                if data.rotation or data.flip:
                    self.window.win.render_copy_ex(texture, source, dest, data.rotation, data.flip)
                else:
                    self.window.win.render_copy(texture, source, dest)

                nb_vertices += 4


    def render_text(self, texts):
        pass