Source code for usf.skin

################################################################################
# copyright 2009 Gabriel Pettier <gabriel.pettier@gmail.com>                   #
#                                                                              #
# This file is part of Ultimate Smash Friends                                  #
#                                                                              #
# Ultimate Smash Friends 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, either version 3 of the License, or (at your   #
# option) any later version.                                                   #
#                                                                              #
# Ultimate Smash Friends 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.                                                                #
#                                                                              #
# You should have received a copy of the GNU General Public License along with #
# Ultimate Smash Friends.  If not, see <http://www.gnu.org/licenses/>.         #
################################################################################

"""
This module allows to customize GUI representation

"""

import os
from os.path import join
import time
from xml.etree.ElementTree import ElementTree

import pygame

# Our modules
from usf import loaders
from usf import CONFIG


[docs]class Skin (object): """ Skin class contains GUI configuration informations. """ def __init__(self): self.dialog = {} self.color = pygame.color.Color("white") self.layer = [] xml_file = ElementTree().parse(os.path.join( CONFIG.system_path, "gui", CONFIG.general.THEME, "theme.xml")) if xml_file.find("color") is not None: self.color = pygame.color.Color( xml_file.find("color").attrib["value"]) if xml_file.find("dialog") is not None: conf_d = xml_file.find("dialog") w, h = CONFIG.general.WIDTH, CONFIG.general.HEIGHT self.dialog["sizex"] = int(conf_d.attrib["sizex"]) * w / 100 self.dialog["sizey"] = int(conf_d.attrib["sizey"]) * h / 100 self.dialog["posx"] = int(conf_d.attrib["posx"]) * w / 100 self.dialog["posy"] = int(conf_d.attrib["posy"]) * h / 100 for node in xml_file.findall("layer"): self.layer.append(Layer(node))
[docs] def get_background(self): """ FIXME: doc! """ pygame.display.get_surface().fill(pygame.color.Color("black")) for layer in self.layer: pygame.display.get_surface().blit( layer.get_image(), layer.get_pos())
[docs]class Layer(object): """ A layer class. It is mainly used to have animated background in both the gui and the game. It is created from an ElementTree xml node. Here is the syntax:: <layer sizex="35" sizey="46" src="path.png"> <frame time="2" x="0" y="-70" /> <frame time="0" x="30" y="600" /> </layer> The path (path.png) of the image must be an absolute path from the data directory of USF, e.g. levels/blobplanet/leaf.png. Time is the duration of the frame (seconds), here, the image will go to the second frame in 2 seconds (and then, it will go to the first in 0). """ def __init__(self, node): self.last_update = 0 self.current = 0 sizex = int(node.attrib["sizex"]) * CONFIG.general.WIDTH/800 sizey = int(node.attrib["sizey"]) * CONFIG.general.HEIGHT/600 self.frame = [] if "type" in node.attrib: self.x = int(node.attrib["x"]) * CONFIG.general.WIDTH/800 self.y = int(node.attrib["y"]) * CONFIG.general.HEIGHT/600 if node.attrib["type"] == "framebyframe": self.type = 1 for frame in node.findall("frame"): src = loaders.image(join(CONFIG.system_path, frame.attrib["src"]), scale=(sizex, sizey))[0] t = float(frame.attrib["time"]) self.frame.append((t, src)) else: self.type = 0 self.background = loaders.image(join(CONFIG.system_path, node.attrib["src"]), scale=(sizex, sizey))[0] for frame in node.findall("frame"): x = int(frame.attrib["x"]) * CONFIG.general.WIDTH/800 y = int(frame.attrib["y"]) * CONFIG.general.HEIGHT/600 t = float(frame.attrib["time"]) self.frame.append((t, (x, y)))
[docs] def get_image(self, dt=-1): """ Get the image surface. :param dt: The current time. Usually, it is -1, and it is set to time.time() when it is -1. It can be useful to specify the time for unit testing. :rtype: pygame surface """ if dt == -1: dt = time.time() if self.last_update + self.frame[self.current][0] < dt: self.last_update = dt if self.current + 1 < len(self.frame): self.current += 1 else: self.current = 0 if self.type == 0: return self.background else: return self.frame[self.current][1]
[docs] def get_pos(self, dt = -1): """ Get the position of the layer. :param dt: The current time. Usually, it is -1, and it is set to time.time() when it is -1. It can be useful to specify the time for unit testing. :rtype: tuple which contains the coordinates of the layer (x, y) """ if self.type == 0: if dt == -1: dt = time.time() interval = dt - self.last_update period = self.frame[self.current][0] position_first = self.frame[self.current][1] position_next = (0, 0) # if we are on the last frame, just return the value of this frame if self.current + 1 < len(self.frame): position_next = self.frame[self.current + 1][1] else: period = 0 # if we are on the first frame, just return it coordinates if period == 0: return self.frame[self.current][1] p = period i = interval x = ((p - i) * position_first[0] + i * position_next[0]) / p y = ((p - i) * position_first[1] + i * position_next[1]) / p position = (x, y) return position else: return(self.x, self.y)