Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCristhofer Travieso <cristhofert97@gmail.com>2012-10-11 16:41:56 (GMT)
committer Cristhofer Travieso <cristhofert97@gmail.com>2012-10-11 16:41:56 (GMT)
commit46d025056b6e0d04edf05bb74f2c3f003c431cd3 (patch)
tree37c7d148c959f4e7328613f414e1649eb9a0aa8d
parentdc1cbc5c0a574a5cbca7543cbdbea5a45dde7232 (diff)
Update glucosa
Signed-off-by: Cristhofer Travieso <cristhofert97@gmail.com>
-rwxr-xr-xgame.py9
-rw-r--r--glucosa.py250
2 files changed, 160 insertions, 99 deletions
diff --git a/game.py b/game.py
index 625c8df..97b9d6a 100755
--- a/game.py
+++ b/game.py
@@ -10,8 +10,8 @@ class Game(glucosa.GameArea):
glucosa.GameArea.__init__(self)
self.events = glucosa.Events(self)
-
head = Head(self.events)
+
self.add_sprite(head)
@@ -19,13 +19,10 @@ class Head(glucosa.Sprite):
def __init__(self, events):
image = glucosa.Image('images/head.png')
glucosa.Sprite.__init__(self, image, 0, 0)
-
- self.events = events
-
- self.events.connect('key-press-event', self.key_pressed)
+ events.connect('key-pressed', self.key_pressed)
def key_pressed(self, widget):
- print 'ok'
+ print "TECLA PRESIONADA"
if __name__ == '__main__':
w = gtk.Window()
diff --git a/glucosa.py b/glucosa.py
index 7bf8fcd..303479b 100644
--- a/glucosa.py
+++ b/glucosa.py
@@ -100,6 +100,36 @@ def _range_between_two_points((x1, y1), (x2, y2)):
"Retorna la distancia entre dos puntos en dos dimensiones."
return math.sqrt(_range(x1, x2) ** 2 + _range(y1, y2) ** 2)
+def dec2hex(dec):
+ """Devulve la representación de una cadena en hexadecimal de un entero"""
+ return "%X" % dec
+
+def hex2dec(hex):
+ """Devuelve el valor entero de una cadena en hexadecimal"""
+ return int(hex, 16)
+
+def get_pixel_color(x, y, surface):
+ """Devuelve el color del pixel solicitado de una surface de cairo."""
+ if isinstance(surface, cairo.Surface):
+ if surface.get_format() == cairo.FORMAT_ARGB32:
+ if surface.get_width() > x >= 0 and surface.get_height() > y >= 0:
+
+ data = surface.get_data()
+
+ bit = surface.get_width() * y * 8 + x * 8
+
+ B = hex2dec(str(data).encode('hex')[bit:bit + 8][0:2])
+ G = hex2dec(str(data).encode('hex')[bit:bit + 8][2:4])
+ R = hex2dec(str(data).encode('hex')[bit:bit + 8][4:6])
+ A = hex2dec(str(data).encode('hex')[bit:bit + 8][6:8])
+
+ return (R, G, B, A)
+ else:
+ raise Exception("Pixel out of range.")
+ else:
+ raise Exception("Only RGBA surfaces are accepted.")
+ else:
+ raise Exception("The surface must be a cairo.Surface.")
def create_window():
"""Genera una ventana con un elemento DrawingArea dentro.
@@ -120,8 +150,6 @@ def create_window():
return (window, canvas)
-# Sume object oriented stuff
-
class Image:
"""Una imagen simple, que puede ser dibujada por un sprite.
@@ -141,6 +169,7 @@ class Image:
anchor_x=anchor_x, anchor_y=anchor_y,
flip=flip)
+
class Frame(Image):
"""Representa un cuadro de animación, realizado dividiendo una imagen.
@@ -236,7 +265,7 @@ class Sprite(gobject.GObject):
__gsignals__ = {
'update': (gobject.SIGNAL_RUN_FIRST, None, [])}
-
+
def __init__(self, image, x, y, anchor_x=0, anchor_y=0, scale=1, rotation=0, flip=False):
gobject.GObject.__init__(self)
self.image = image
@@ -249,15 +278,14 @@ class Sprite(gobject.GObject):
self.flip = flip
self.radius = (max(self.image.width, self.image.height) / 2)
- def set_pos(self, x = -1, y = -1):
+ def set_pos(self, x=None, y=None):
"""Define la posicion del personaje"""
- if x >= 0:
+ if x:
self.x = x
-
- if y >= 0:
+
+ if y:
self.y = y
- self.emit('update')
-
+
def move(self, mx=0, my=0):
"""Mueve el personaje basandose en la posicion actual
Ejemplo:
@@ -265,12 +293,12 @@ class Sprite(gobject.GObject):
>>> sprite.move(0, +10) # Aumentara 10 pixels en y"""
self.x += mx
self.y += mx
-
+
def set_anchor(self, x = -1, y = -1):
"""Define el punto de control del personaje"""
if x >= 0:
self.anchor_x = x
-
+
if y >= 0:
self.anchor_y = y
self.emit('update')
@@ -282,16 +310,27 @@ class Sprite(gobject.GObject):
def set_flip(self, flip):
"""Espejado horizontal"""
- self.flip = flip
+ self._flip = flip
self.emit('update')
+ def get_flip(self):
+ return self._flip
+
+ flip = property(get_flip, set_flip, doc="Espejado horizontal")
+
def set_image(self, image):
+ """Define la imagen del sprite"""
self.image = image
self.emit('update')
+ def set_scale(self, scale):
+ """Escalar el sprite"""
+ self.scale = scale
+ self.emit('update')
+
def draw(self, context):
""" Dibuja un el sprite en el contexto """
- self.image.blit(context, self.x, self.y, scale=self.scale, rotation=self.rotation, anchor_x=self.anchor_x, anchor_y=self.anchor_y, flip=self.flip)
+ self.image.blit(context, self._x, self._y, scale=self.scale, rotation=self.rotation, anchor_x=self.anchor_x, anchor_y=self.anchor_y, flip=self._flip)
def update(self):
""" Actualiza el estado de la animación del Sprite si el Sprite contiene un Frame,
@@ -308,7 +347,54 @@ class Sprite(gobject.GObject):
"Retorna True si el sprite colisiona con otro sprite."
return _range_between_two_points(self.get_center(), sprite.get_center()) < self.radius + sprite.radius
+ def set_x(self, x):
+ self._x = x
+ self.emit('update')
+
+ def set_y(self, y):
+ self._y = y
+ self.emit('update')
+
+ def get_x(self):
+ return self._x
+
+ def get_y(self):
+ return self._y
+
+ x = property(get_x, set_x, doc="Define la posicion horizonal")
+ y = property(get_y, set_y, doc="Define la posicion vertical")
+
+ def get_left(self):
+ return self.x - (self.image.width * self.scale / 2)
+
+ def set_left(self, x):
+ self.x = x + (self.image.width * self.scale / 2)
+
+ def get_right(self):
+ return self.left + (self.image.width * self.scale)
+
+ def set_right(self, x):
+ self.set_left(x - self.image.width * self.scale)
+
+ left = property(get_left, set_left, doc="Define la posición izquierda del Sprite")
+ right = property(get_right, set_right, doc="Define la posición derecha del Sprite")
+
+ def get_top(self):
+ return self.y - (self.image.height * self.scale / 2)
+
+ def set_top(self, y):
+ self.y = y + (self.image.height * self.scale / 2)
+ def get_bottom(self):
+ return self.top + (self.image.height * self.scale)
+
+ def set_bottom(self, y):
+ self.set_top(y - self.image.height * self.scale)
+
+ top = property(get_top, set_top, doc="Define la posición superior del Sprite")
+ bottom = property(get_bottom, set_bottom, doc="Define la posición inferior del Sprite")
+
+
class Text:
"""Muestra un texto en la pantalla.
@@ -371,85 +457,42 @@ class Singleton(type):
return self.instance
-class _EventsManager:
-
- # Listado de eventos a capturar.
- __events__ = ('on_mouse_move',
- 'on_mouse_button_pressed',
- 'on_mouse_button_released',
- 'on_mouse_scroll_up',
- 'on_mouse_scroll_down',
- 'on_key_pressed',
- 'on_key_released')
-
- def __getattr__(self, name):
- if hasattr(self.__class__, '__events__'):
- assert name in self.__class__.__events__, \
- "Event '%s' is not declared" % name
- self.__dict__[name] = ev = _EventSlot(name)
- return ev
-
- def __repr__(self): return 'Events' + str(list(self))
-
- __str__ = __repr__
-
- def __len__(self): return NotImplemented
-
- def __iter__(self):
- def gen(dictitems = self.__dict__.items()):
- for attr, val in dictitems:
- if isinstance(val, _EventSlot):
- yield val
- return gen()
-
-class _EventSlot:
- """ Evento generico al que se agregan observadores para ser informados
- de cuando se ha producido dicho evento. """
-
- def __init__(self, name):
- self.targets = []
- self.__name__ = name
-
- def __repr__(self):
- return 'event ' + self.__name__
-
- def __call__(self, *a, **kw):
- for f in self.targets: f(*a, **kw)
-
- def __iadd__(self, f):
- self.targets.append(f)
- return self
-
- def __isub__(self, f):
- while f in self.targets: self.targets.remove(f)
- return self
-
-class Events(_EventsManager, object):
+class Events(gobject.GObject):
""" Gestor de los posibles eventos que se producen en glucosa.
>>> def boton_mouse_presionado(self, evento):
>>> print evento
>>>
- >>> eventos = glucosa.Events(self.window)
- >>> eventos.on_mouse_button_pressed += self.boton_mouse_presionado
+ >>> eventos = glucosa.AreaEvents(self.window)
+ >>> eventos.connect('mouse-button-pressed', self.boton_mouse_presionado)
Los posibles eventos a los que se puede conectar un metodo son:
- - on_mouse_move ( al mover el raton por la pantalla ).
- - on_mouse_button_pressed ( al soltar un botón del ratón ).
- - on_mouse_button_released ( al presionar un btoón del ratón ).
- - on_mouse_scroll_up ( al mover la rueda central del raton hacia arriba ).
- - on_mouse_scroll_down ( al mover la rueda central del raton hacia abajo ).
- - on_key_pressed ( al pulsar una tecla ).
- - on_key_released ( al soltar una tecla ).
+ - mouse-moved ( al mover el raton por la pantalla ).
+ - mouse-button-pressed ( al soltar un botón del ratón ).
+ - mouse-button-released ( al presionar un btoón del ratón ).
+ - mouse-scroll-up ( al mover la rueda central del raton hacia arriba ).
+ - mouse-scroll-down ( al mover la rueda central del raton hacia abajo ).
+ - key-pressed ( al pulsar una tecla ).
+ - key-released ( al soltar una tecla ).
"""
+ # No funciona con gobject:
# Solo puede existir una instancia de este objeto en el programa.
- __metaclass__ = Singleton
+ #__metaclass__ = Singleton
+
+ __gsignals__ = {'mouse-moved': (gobject.SIGNAL_RUN_FIRST, None, [object]),
+ 'mouse-button-pressed': (gobject.SIGNAL_RUN_FIRST, None, [object]),
+ 'mouse-button-released': (gobject.SIGNAL_RUN_FIRST, None, [object]),
+ 'mouse-scroll-up': (gobject.SIGNAL_RUN_FIRST, None, [object]),
+ 'mouse-scroll-down': (gobject.SIGNAL_RUN_FIRST, None, [object]),
+ 'key-pressed': (gobject.SIGNAL_RUN_FIRST, None, []),
+ 'key-released': (gobject.SIGNAL_RUN_FIRST, None, [])}
def __init__(self, widget):
+ gobject.GObject.__init__(self)
self._widget = widget
@@ -472,21 +515,21 @@ class Events(_EventsManager, object):
def _mouse_move(self, widget, event):
mouse_event = {'x' : event.x,
'y' : event.y}
- self.on_mouse_move(mouse_event)
+ self.emit('mouse-moved', mouse_event)
return True
def _mouse_button_press(self, widget, event):
mouse_event = {'button' : event.button,
'x' : event.x,
'y' : event.y}
- self.on_mouse_button_pressed(mouse_event)
+ self.emit('mouse-button-pressed', mouse_event)
return True
def _mouse_button_released(self, widget, event):
mouse_event = {'button' : event.button,
'x' : event.x,
'y' : event.y}
- self.on_mouse_button_released(mouse_event)
+ self.emit('mouse-button-released', mouse_event)
return True
def _mouse_scroll(self, widget, event):
@@ -494,10 +537,10 @@ class Events(_EventsManager, object):
'y' : event.y}
if (event.direction == self.scroll_up):
- self.on_mouse_scroll_up(mouse_event)
+ self.emit('mouse-scroll-up', mouse_event)
if (event.direction == self.scroll_down):
- self.on_mouse_scroll_down(mouse_event)
+ self.emit('mouse-scroll-down', mouse_event)
return True
@@ -510,7 +553,7 @@ class Events(_EventsManager, object):
return (key in self._keys_pressed)
def _key_repeater(self):
- self.on_key_pressed()
+ self.emit('key-pressed')
return len(self._keys_pressed) > 0
def _key_pressed(self, widget, event):
@@ -523,14 +566,14 @@ class Events(_EventsManager, object):
gobject.timeout_add(10, self._key_repeater)
self._register_key(keyvalue)
- self.on_key_pressed()
+ self.emit('key-pressed')
return True
def _key_released(self, widget, event):
keyvalue = gtk.gdk.keyval_name(event.keyval)
self._unregister_key(keyvalue)
- self.on_key_released()
+ self.emit('key-released')
return True
def _register_key(self, key):
@@ -695,10 +738,10 @@ class Pencil:
class GameArea(gtk.DrawingArea):
"""Es el area donde el juego se dibujará
-
+
Permite ser embebida en cualquier contenedor de gtk, ya que es un
widget.
-
+
Emite un señal en cada actualizacion y en cada redibujado
que pueden ser usadas de la siguiente forma:
>>> area.connect('update', funcion_a_llamar)
@@ -712,11 +755,14 @@ class GameArea(gtk.DrawingArea):
def __init__(self):
gtk.DrawingArea.__init__(self)
-
+
self.sprites = []
+ self._timeout = None
+
+ self._backgroud = None
self.connect("expose-event", self._on_draw)
-
+
self.set_events( gtk.gdk.BUTTON_PRESS_MASK
| gtk.gdk.BUTTON_RELEASE_MASK
| gtk.gdk.KEY_RELEASE_MASK
@@ -729,16 +775,29 @@ class GameArea(gtk.DrawingArea):
"""Agrega un sprite a el area de juego"""
self.sprites.append(sprite)
sprite.connect('update', self._update)
+
+ def set_background(self, background):
+ """Define el fondo del area de juego"""
+ self._background = background
+ self.queue_draw()
+
+ def set_update_loop(self, fps=60):
+ """Define un bucle de actualizacion si fps = -1 el bucle se detendra
+ y dibujara solo cuando un sprite cambie"""
+ if self._timeout:
+ gobject.source_remove(self._timeout)
+ if fps != -1:
+ self._timeout = gobject.timeout_add(1000/60, self._update)
def _update(self, *args):
# Emite la señal, llamando a todas las funciones que esten conectadas
# en este caso no pasa argumentos.
self.emit('update')
-
+
# Se actualizan los sprites
for sprite in self.sprites:
sprite.update()
-
+
gobject.idle_add(self.queue_draw)
return True
@@ -746,10 +805,15 @@ class GameArea(gtk.DrawingArea):
context = self.window.cairo_create()
window_size = self.get_window().get_size()
fill(context, (50,50,50), window_size)
-
+
+ # Dibuja el fondo
+ if self._backgroud:
+ self._backgroud.blit(context, 0, 0, scale=1, rotation=0, anchor_x=0,
+ anchor_y=0, flip=False)
+
# Se encarga de dibujar los sprites
for sprite in self.sprites:
sprite.draw(context)
-
+
# Emite la señal enviando el context como un argumento
self.emit('draw', context)