def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = [colors[0]] self._colors.append(colors[1]) self._mun_color = MunColor() self._dot_cache = {} self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.connect("draw", self.__draw_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = smallest_size / (DOT_SIZE*8) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self.max_levels = len(LEVELS_TRUE) self.this_pattern = False # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] self._generate_grid()
def formatTerr(self, worldTerritories, territorySprites, highlightedTerritories, gui, colorTerritories, textList, map): for i, j in enumerate(worldTerritories): surface = pygame.image.load(j).convert() resize = c.windowLength / surface.get_width() surface = pygame.transform.scale( surface, (int(resize * surface.get_width()), int(resize * surface.get_height()))) territorySprite = Sprites(surface, j) initialSpriteLayer = Sprites(surface.copy(), j) gui.setSurfaceColor(initialSpriteLayer, (1, 1, 1), 150) territorySprites.append(territorySprite) highlightedTerritories.append(initialSpriteLayer) # Creates final layer of all connected sprites colorTerritories(territorySprites, gui) for i, j in enumerate(territorySprites): if i == 0: finalLayout = j.layout.copy() else: finalLayout.blit(j.layout, (0, 0)) # Update visual troop numbers gui.troopDisplay(textList, territorySprites, map) return finalLayout
def _setup_workspace(self): ''' Add the bones. ''' self._width = Gdk.Screen.width() self._height = int(Gdk.Screen.height() - (GRID_CELL_SIZE * 2)) self._scale = self._height * 1.0 / BONE_HEIGHT self._bone_width = int(BONE_WIDTH * self._scale) self._bone_height = int(BONE_HEIGHT * self._scale) # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._bone_index = Sprite( self._sprites, 0, 0, _load_svg_from_file( os.path.join(self._bone_path, 'bones-index.svg'), self._bone_width, self._bone_height)) self._max_bones = int(self._width / self._bone_width) - 1 self._blank_image = _load_svg_from_file( os.path.join(self._bone_path, 'blank-bone.svg'), self._bone_width, self._bone_height) for bones in range(self._max_bones): self._bones.append( Sprite(self._sprites, bones * self._bone_width, 0, self._blank_image)) circle_image = _load_svg_from_file( os.path.join(self._bone_path, 'circle.svg'), int(self._scale * 45), int(self._scale * 45)) self._circles[0] = Sprite(self._sprites, 0, -100, circle_image) self._circles[1] = Sprite(self._sprites, 0, -100, circle_image) oval_image = _load_svg_from_file( os.path.join(self._bone_path, 'oval.svg'), int(self._scale * 129), int(self._scale * 92)) for bones in range(self._max_bones - 1): self._ovals.append(Sprite(self._sprites, 0, -100, oval_image))
def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = [colors[0]] self._colors.append(colors[1]) self._colors.append('#D0D0D0') self._colors.append('#000000') self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._width / (10 * DOT_SIZE * 1.2) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self.we_are_sharing = False self._edge = 4 self._move_list = [] # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] self._generate_grid()
def __init__(self, canvas, parent=None, path=None, colors=['#A0FFA0', '#FF8080']): self._canvas = canvas self._parent = parent self._parent.show_all() self._path = path self.level = 1 self._colors = ['#FFFFFF'] self._colors.append(colors[0]) self._colors.append(colors[1]) self._colors.append(colors[0]) self._colors.append('#FF0000') self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - GRID_CELL_SIZE if self._width < self._height: self.portrait = True self.grid_height = TEN self.grid.width = SEVEN else: self.portrait = False self.grid_height = SEVEN self.grid_width = TEN self._scale = min(self._width / (self.grid_width * DOT_SIZE * 1.2), self._height / (self.grid_height * DOT_SIZE * 1.2)) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self.we_are_sharing = False # '-1' Workaround for showing 'second 0' self._game_time_seconds = -1 self._game_time = "00:00" self._timeout_id = None # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] for y in range(self.grid_height): for x in range(self.grid_width): xoffset = int((self._width - self.grid_width * self._dot_size - (self.grid_width - 1) * self._space) / 2.) self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space), self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set self._dots[-1].set_label_attributes(40) self._all_clear() Gdk.Screen.get_default().connect('size-changed', self._configure_cb)
def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = colors self._canvas = canvas parent.show_all() self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._height / (14.0 * DOT_SIZE * 1.2) self._dot_size = int(DOT_SIZE * self._scale) self._turtle_offset = 0 self._space = int(self._dot_size / 5.) self._orientation = 0 self.level = 0 self.custom_strategy = None self.strategies = [ BEGINNER_STRATEGY, INTERMEDIATE_STRATEGY, EXPERT_STRATEGY, self.custom_strategy ] self.strategy = self.strategies[self.level] self._timeout_id = None # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] for y in range(THIRTEEN): for x in range(THIRTEEN): xoffset = int((self._width - THIRTEEN * (self._dot_size + \ self._space) - self._space) / 2.) if y % 2 == 1: xoffset += int((self._dot_size + self._space) / 2.) if x == 0 or y == 0 or x == THIRTEEN - 1 or y == THIRTEEN - 1: self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space), self._new_dot('#B0B0B0'))) else: self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space), self._new_dot(self._colors[FILL]))) self._dots[-1].type = False # not set # Put a turtle at the center of the screen... self._turtle_images = [] self._rotate_turtle(self._new_turtle()) self._turtle = Sprite(self._sprites, 0, 0, self._turtle_images[0]) self._move_turtle(self._dots[int(THIRTEEN * THIRTEEN / 2)].get_xy()) # ...and initialize. self._all_clear()
def __init__(self, misc): pygame.sprite.Sprite.__init__(self) misc_list = Sprites("heart2.png") image = misc_list.get_image(0, 0, 1, 1) color_switch = image.get_at((0, 0)) self.image = misc_list.get_image(misc[0], misc[1], misc[2], misc[3]) self.image.set_colorkey(color_switch) self.rect = self.image.get_rect()
def __init__(self, misc): Entity.__init__(self) misc_list = Sprites("heart.png") image = misc_list.get_image(0, 0, 48, 48) color_switch = image.get_at((0, 0)) self.image = misc_list.get_image(misc[0], misc[1], misc[2], misc[3]) self.image.set_colorkey(color_switch) self.rect = self.image.get_rect()
def __init__(self, sprite_sheet_data): pygame.sprite.Sprite.__init__(self) sprite_sheet = Sprites("scifi_platformTiles_32x32.png") self.image = sprite_sheet.get_image(sprite_sheet_data[0], sprite_sheet_data[1], sprite_sheet_data[2], sprite_sheet_data[3]) self.rect = self.image.get_rect()
def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self.colors = colors # Starting from command line if parent is None: self._running_sugar = False self._canvas = canvas else: self._running_sugar = True self._canvas = canvas parent.show_all() self._canvas.set_can_focus(True) self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK) self._canvas.connect("draw", self._draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._canvas.connect("button-release-event", self._button_release_cb) self._canvas.connect("motion-notify-event", self._mouse_move_cb) self._canvas.connect("key_press_event", self._keypress_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._height / (8.0 * TILE_HEIGHT) self.tile_width = TILE_WIDTH * self._scale self.tile_height = TILE_HEIGHT * self._scale # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self.grid = Grid(self._sprites, self._width, self._height, self.tile_width, self.tile_height, self._scale, colors[0]) self.deck = Deck(self._sprites, self._scale, colors[1]) self.deck.board.move((self.grid.left, self.grid.top)) self.hands = [] self.hands.append(Hand(self.tile_width, self.tile_height)) self._errormsg = [] for i in range(4): self._errormsg.append(error_graphic(self._sprites)) self._highlight = highlight_graphic(self._sprites, self._scale) self._score_card = blank_tile(self._sprites, scale=self._scale * 2, color=colors[1]) self._score_card.set_label_attributes(64) self._score_card.move(((int(self._width / 2) - self.tile_width), int(self._height / 2) - self.tile_height)) # and initialize a few variables we'll need. self.buddies = [] self._my_hand = MY_HAND self.playing_with_robot = False self._all_clear()
def __init__(self, coins): pygame.sprite.Sprite.__init__(self) coin_list = Sprites("coin_silver.png") image = coin_list.get_image(0, 0, 1, 1) color_switch = image.get_at((0, 0)) self.image = coin_list.get_image(coins[0], coins[1], coins[2], coins[3]) self.image.set_colorkey(color_switch) self.rect = self.image.get_rect()
def __init__(self, enemies): pygame.sprite.Sprite.__init__(self) enemy_list = Sprites("spikez.png") image = enemy_list.get_image(0, 0, 1, 1) color_switch = image.get_at((0, 0)) self.image = enemy_list.get_image(enemies[0], enemies[1], enemies[2], enemies[3]) self.image.set_colorkey(color_switch) self.rect = self.image.get_rect()
def __init__(self, canvas, parent=None, mycolors=['#A0FFA0', '#FF8080']): self._activity = parent self.colors = [mycolors[0]] self.colors.append(mycolors[1]) self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.connect("draw", self.__draw_cb) self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("button-press-event", self._button_press_cb) self._canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK) self._canvas.connect('button-release-event', self._button_release_cb) self._canvas.add_events(Gdk.EventMask.POINTER_MOTION_MASK) self._canvas.connect("motion-notify-event", self._mouse_move_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - GRID_CELL_SIZE self._scale = self._width / 1200. self.press = None self.dragpos = [0, 0] self.startpos = [0, 0] self._dot_cache = {} self._xo_cache = {} self._radius = 22.5 self._stroke_width = 9.5 # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] self._xo_man = None self._generate_bg('#FFF') # First dot, starting angle self._cxy = [self._width / 2, self._height / 2] self._xy = [ self._width / 2 + 120 * self._scale, self._height / 2 - self._radius * self._scale ] self._angle = 0 self._dot_size_plus = self._radius * 3 * self._scale self._min = -self._dot_size_plus / 3 self._max = self._height - (self._dot_size_plus / 2.2) self._zones = [] self._calc_zones() self._generate_spiral()
def __init__(self, sprite_sheet_data): Entity.__init__(self) sprite_sheet = Sprites("tiles.png") image = sprite_sheet.get_image(0, 0, 1, 1) color_switch = image.get_at((0, 0)) self.image = sprite_sheet.get_image(sprite_sheet_data[0], sprite_sheet_data[1], sprite_sheet_data[2], sprite_sheet_data[3]) self.image.set_colorkey(color_switch) self.rect = self.image.get_rect()
def _setup_workspace(self): ''' Add the bones. ''' self._width = Gdk.Screen.width() self._height = int(Gdk.Screen.height() - (GRID_CELL_SIZE * 2)) self._scale = self._height * 1.0 / BONE_HEIGHT self._bone_width = int(BONE_WIDTH * self._scale) self._bone_height = int(BONE_HEIGHT * self._scale) # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._bone_index = Sprite(self._sprites, 0, 0, _load_svg_from_file( os.path.join(self._bone_path, 'bones-index.svg'), self._bone_width, self._bone_height)) self._max_bones = int(self._width / self._bone_width) - 1 self._blank_image = _load_svg_from_file( os.path.join(self._bone_path, 'blank-bone.svg'), self._bone_width, self._bone_height) for bones in range(self._max_bones): self._bones.append(Sprite(self._sprites, bones * self._bone_width, 0, self._blank_image)) circle_image = _load_svg_from_file( os.path.join(self._bone_path, 'circle.svg'), int(self._scale * 45), int(self._scale * 45)) self._circles[0] = Sprite(self._sprites, 0, -100, circle_image) self._circles[1] = Sprite(self._sprites, 0, -100, circle_image) oval_image = _load_svg_from_file( os.path.join(self._bone_path, 'oval.svg'), int(self._scale * 129), int(self._scale * 92)) for bones in range(self._max_bones - 1): self._ovals.append(Sprite(self._sprites, 0, -100, oval_image))
def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = [colors[0]] self._colors.append(colors[1]) self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.set_flags(gtk.CAN_FOCUS) self._canvas.connect("expose-event", self._expose_cb) self._width = gtk.gdk.screen_width() self._height = gtk.gdk.screen_height() - (GRID_CELL_SIZE * 1.5) self._scale = self._width / (10 * DOT_SIZE * 1.2) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self.max_levels = len(LEVELS_TRUE) self.this_pattern = False # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] self._generate_grid()
def __init__(self, canvas, parent=None, path=None, colors=['#A0FFA0', '#FF8080']): self._canvas = canvas self._parent = parent self._parent.show_all() self._path = path self._colors = ['#FFFFFF'] self._colors.append(colors[0]) self._colors.append(colors[1]) self._canvas.connect('draw', self.__draw_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._height / (3 * DOT_SIZE * 1.2) self._scale /= 1.5 self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self.we_are_sharing = False self._start_time = 0 self._timeout_id = None # Find the image files self._PATHS = glob.glob(os.path.join(self._path, 'images', '*.svg')) # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] yoffset = self._space * 2 # int(self._space / 2.) for y in range(3): for x in range(3): xoffset = int((self._width - 3 * self._dot_size - \ 2 * self._space) / 2.) self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space) + yoffset, self._new_dot_surface(color=self._colors[0]))) self._dots[-1].type = -1 # No image self._dots[-1].set_label_attributes(72)
def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = colors self._canvas = canvas parent.show_all() self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._height / (14.0 * DOT_SIZE * 1.2) self._dot_size = int(DOT_SIZE * self._scale) self._turtle_offset = 0 self._space = int(self._dot_size / 5.) self._orientation = 0 self.level = 0 self.custom_strategy = None self.strategies = [BEGINNER_STRATEGY, INTERMEDIATE_STRATEGY, EXPERT_STRATEGY, self.custom_strategy] self.strategy = self.strategies[self.level] self._timeout_id = None # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] for y in range(THIRTEEN): for x in range(THIRTEEN): xoffset = int((self._width - THIRTEEN * (self._dot_size + \ self._space) - self._space) / 2.) if y % 2 == 1: xoffset += int((self._dot_size + self._space) / 2.) if x == 0 or y == 0 or x == THIRTEEN - 1 or y == THIRTEEN - 1: self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space), self._new_dot('#B0B0B0'))) else: self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space), self._new_dot(self._colors[FILL]))) self._dots[-1].type = False # not set # Put a turtle at the center of the screen... self._turtle_images = [] self._rotate_turtle(self._new_turtle()) self._turtle = Sprite(self._sprites, 0, 0, self._turtle_images[0]) self._move_turtle(self._dots[int(THIRTEEN * THIRTEEN / 2)].get_xy()) # ...and initialize. self._all_clear()
def __init__(self, canvas, path, parent=None): """ Initialize the playing surface """ self.path = path self.activity = parent # starting from command line # we have to do all the work that was done in CardSortActivity.py if parent is None: self.sugar = False self.canvas = canvas # starting from Sugar else: self.sugar = True self.canvas = canvas parent.show_all() self.canvas.set_flags(gtk.CAN_FOCUS) self.canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK) self.canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK) self.canvas.connect("expose-event", self._expose_cb) self.canvas.connect("button-press-event", self._button_press_cb) self.canvas.connect("button-release-event", self._button_release_cb) self.canvas.connect("key_press_event", self._keypress_cb) self.width = gtk.gdk.screen_width() self.height = gtk.gdk.screen_height() - GRID_CELL_SIZE self.card_dim = CARD_DIM self.scale = 0.6 * self.height / (self.card_dim * 3) # Initialize the sprite repository self.sprites = Sprites(self.canvas) # Initialize the grid self.mode = 'rectangle' self.grid = Grid(self, self.mode) self.bounds = LEVEL_BOUNDS[0] self.level = 0 # Start solving the puzzle self.press = None self.release = None self.start_drag = [0, 0]
def __init__(self, canvas, parent=None): """ Initialize the canvas and set up the callbacks. """ self.activity = parent if parent is None: # Starting from command line self.sugar = False self.canvas = canvas else: # Starting from Sugar self.sugar = True self.canvas = canvas parent.show_all() self.canvas.set_flags(gtk.CAN_FOCUS) self.canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK) self.canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK) self.canvas.add_events(gtk.gdk.POINTER_MOTION_MASK) self.canvas.connect("expose-event", self._expose_cb) self.canvas.connect("button-press-event", self._button_press_cb) self.canvas.connect("button-release-event", self._button_release_cb) self.canvas.connect("motion-notify-event", self._mouse_move_cb) self.width = gtk.gdk.screen_width() self.height = gtk.gdk.screen_height()-GRID_CELL_SIZE self.sprites = Sprites(self.canvas) self.scale = gtk.gdk.screen_height()/900.0 self.dragpos = 0 self.press = None self.chinese = Suanpan(self) self.japanese = Soroban(self) self.russian = Schety(self) self.mayan = Nepohualtzintzin(self) self.binary = Binary(self) self.hex = Hex(self) self.fraction = Fractions(self) self.custom = None self.chinese.show() self.japanese.hide() self.russian.hide() self.mayan.hide() self.binary.hide() self.hex.hide() self.fraction.hide() self.mode = self.chinese
def inicializar_jogo(self): self.ambiente = pygame self.ambiente.init() self.sprites = Sprites(pygame) self.inputs = Inputs(self.ambiente) self.clock_soldados_atiradores = self.ambiente.time.get_ticks() self.clock_soldados_espada = self.ambiente.time.get_ticks() self.clock_corvo = self.ambiente.time.get_ticks() self.paused = False self.cont_background = 0 self.width = 1280 self.height = 768 self.device_screen = self.ambiente.display.Info() print(self.device_screen.current_w) self.screen = self.ambiente.display.set_mode([self.width, self.height], self.ambiente.FULLSCREEN | self.ambiente.DOUBLEBUF) self.background_imgs = [self.ambiente.image.load('imagens/mapa/mapa_1.png').convert(), self.ambiente.image.load('imagens/mapa/mapa_2.png').convert(),\ self.ambiente.image.load('imagens/mapa/mapa_3.png').convert(), self.ambiente.image.load('imagens/mapa/mapa_4.png').convert()] self.background_image = self.background_imgs[0] self.torre = self.ambiente.image.load( 'imagens/torre.png').convert_alpha() self.indio = Indio(self.ambiente, 3, 1000, 0, 510) self.cd = Cooldown(self.ambiente, 20, 490) self.barra = Barra(self.ambiente, 10, 650) self.lanca = Lanca(self.ambiente, 1, 0, 0, 20, 510, 0, 90) self.barreira1 = Barreira(self.ambiente, 2, 400, 300, 'top') self.barreira2 = Barreira(self.ambiente, 3, 400, 500, 'bot') self.sprites.barreiras.add(self.barreira1, self.barreira2) self.sprites.indio.add(self.indio) self.sprites.todos_objetos.add(self.sprites.indio, self.barra, self.sprites.barreiras) self.clock_mapa = self.ambiente.time.get_ticks() self.time = self.ambiente.time.get_ticks() self.seta_menu = Seta(self.ambiente, 350, 200) self.menu_background = self.ambiente.image.load( 'imagens/menu_background.png') self.ambiente.font.init() self.fonte = self.ambiente.font.SysFont('Comic Sans MS', 30) self.screen.blit(self.background_image, [0, 0])
def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self.colors = colors # Starting from command line if parent is None: self._running_sugar = False self._canvas = canvas else: self._running_sugar = True self._canvas = canvas parent.show_all() self._canvas.set_flags(gtk.CAN_FOCUS) self._canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK) self._canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK) self._canvas.add_events(gtk.gdk.POINTER_MOTION_MASK) self._canvas.connect("expose-event", self._expose_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._canvas.connect("button-release-event", self._button_release_cb) self._canvas.connect("motion-notify-event", self._mouse_move_cb) self._canvas.connect("key_press_event", self._keypress_cb) self._width = gtk.gdk.screen_width() self._height = gtk.gdk.screen_height() - (GRID_CELL_SIZE * 1.5) self._scale = self._height / (8.0 * TILE_HEIGHT) self.tile_width = TILE_WIDTH * self._scale self.tile_height = TILE_HEIGHT * self._scale # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self.grid = Grid(self._sprites, self._width, self._height, self.tile_width, self.tile_height, self._scale, colors[0]) self.deck = Deck(self._sprites, self._scale, colors[1]) self.deck.board.move((self.grid.left, self.grid.top)) self.hands = [] self.hands.append(Hand(self.tile_width, self.tile_height)) self._errormsg = [] for i in range(4): self._errormsg.append(error_graphic(self._sprites)) self._highlight = highlight_graphic(self._sprites, self._scale) self._score_card = blank_tile(self._sprites, scale=self._scale * 2, color=colors[1]) self._score_card.set_label_attributes(64) self._score_card.move(((int(self._width / 2) - self.tile_width), int(self._height / 2) - self.tile_height)) # and initialize a few variables we'll need. self.buddies = [] self._my_hand = MY_HAND self.playing_with_robot = False self._all_clear()
def __init__(self, x, y, xvel): Entity.__init__(self) # Create Surface Area self.image = pygame.Surface((90, 90), pygame.SRCALPHA) self.rect = pygame.Rect(0, 0, 80, 80) # Initialize variables self.xvel = xvel self.yvel = 0 self.rect.x = x self.rect.y = y self.boundary_left = 0 self.boundary_right = 1000 # States self.onGround = False self.airborne = True self.destroyed = False self.faceright = True self.counter = 0 # Load Sprites sprites = Sprites("bat8.png") image = sprites.get_image(15, 9, 67, 73) color_switch = image.get_at((0, 0)) image.set_colorkey(color_switch) self.walkleft.append(image) image = pygame.transform.flip(image, True, False) self.walkright.append(image) sprites = Sprites("bat9.png") image = sprites.get_image(18, 11, 73, 69) color_switch = image.get_at((0, 0)) image.set_colorkey(color_switch) self.walkleft.append(image) image = pygame.transform.flip(image, True, False) self.walkright.append(image) sprites = Sprites("bat10.png") image = sprites.get_image(20, 26, 59, 35) color_switch = image.get_at((0, 0)) image.set_colorkey(color_switch) self.walkleft.append(image) image = pygame.transform.flip(image, True, False) self.walkright.append(image)
def __init__(self, canvas, parent=None, mycolors=['#A0FFA0', '#FF8080']): self._activity = parent self.colors = [mycolors[0]] self.colors.append(mycolors[1]) self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.connect("draw", self.__draw_cb) self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("button-press-event", self._button_press_cb) self._canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK) self._canvas.connect('button-release-event', self._button_release_cb) self._canvas.add_events(Gdk.EventMask.POINTER_MOTION_MASK) self._canvas.connect("motion-notify-event", self._mouse_move_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - GRID_CELL_SIZE self._scale = self._width / 1200. self.press = None self.dragpos = [0, 0] self.startpos = [0, 0] self._dot_cache = {} self._xo_cache = {} self._radius = 22.5 self._stroke_width = 9.5 # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._sprites.set_delay(True) self._dots = [] self._xo_man = None self._generate_bg('#FFF') # First dot, starting angle self._cxy = [self._width / 2, self._height / 2] self._xy = [self._width / 2 + 120 * self._scale, self._height / 2 - self._radius * self._scale] self._angle = 0 self._dot_size_plus = self._radius * 3 * self._scale self._min = -self._dot_size_plus / 3 self._max = self._height - (self._dot_size_plus / 2.2) self._zones = [] self._calc_zones() self._generate_spiral() self._sprites.draw_all()
def __init__(self, canvas, path, parent=None): self.activity = parent self.path = path # starting from command line # we have to do all the work that was done in CardSortActivity.py if parent is None: self.sugar = False self.canvas = canvas # starting from Sugar else: self.sugar = True self.canvas = canvas parent.show_all() self.canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self.canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK) self.canvas.connect("draw", self.__draw_cb) self.canvas.connect("button-press-event", self._button_press_cb) self.canvas.connect("button-release-event", self._button_release_cb) self.width = Gdk.Screen.width() self.height = Gdk.Screen.height() - style.GRID_CELL_SIZE self.height = Gdk.Screen.height() - style.GRID_CELL_SIZE self.card_dim = CARD_DIM self.scale = 0.8 * self.height / (self.card_dim * 3) # Initialize the sprite repository self.sprites = Sprites(self.canvas) # Initialize the grid self.grid = Grid(self) # Start solving the puzzle self.press = -1 self.release = -1 self.start_drag = [0, 0]
def __init__(self): pygame.sprite.Sprite.__init__(self) sprites = Sprites("E:\Programming\Python\mygame\Xeonsheet.bmp") #Right side sprites image = sprites.get_image(17, 5, 45, 71) color_switch = image.get_at((0, 0)) image.set_colorkey(color_switch) self.walking_frames_r.append(image) image = sprites.get_image(25, 170, 45, 71) #59,66 color_switch = image.get_at((2, 2)) image.set_colorkey(color_switch) self.walking_frames_r.append(image) image = sprites.get_image(103, 170, 45, 72) #59,66 color_switch = image.get_at((2, 2)) image.set_colorkey(color_switch) self.walking_frames_r.append(image) # Left side sprites image = sprites.get_image(17, 5, 45, 72) image.set_colorkey(color_switch) image = pygame.transform.flip(image, True, False) self.walking_frames_l.append(image) image = sprites.get_image(25, 170, 55, 71) # 59,66 color_switch = image.get_at((2, 2)) image.set_colorkey(color_switch) image = pygame.transform.flip(image, True, False) self.walking_frames_l.append(image) image = sprites.get_image(103, 170, 55, 72) # 59,66 color_switch = image.get_at((2, 2)) image.set_colorkey(color_switch) image = pygame.transform.flip(image, True, False) self.walking_frames_l.append(image) # Arxiko sprite self.image = self.walking_frames_r[0] self.rect = self.image.get_rect()
def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = [colors[0]] self._colors.append(colors[1]) self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.connect("draw", self.__draw_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._width / (10 * DOT_SIZE * 1.2) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self.max_levels = len(LEVELS_TRUE) self.this_pattern = False # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] self._generate_grid()
def __init__(self, canvas, parent=None, path=None): self._canvas = canvas self._parent = parent self._parent.show_all() self._path = path self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() self._scale = self._width / 1200. self._target = 0 self._tries = 0 self.level = 0 self._picture_cards = [] self._small_picture_cards = [] self.food_cards = [] self._group_cards = [] self._quantity_cards = [] self._balance_cards = [] self._last_twenty = [] self._background = None # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._background = Sprite( self._sprites, 0, 0, GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images','background.png'), self._width, self._height)) self._background.set_layer(0) self._background.type = None self._background.hide() self.pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'word-box.png'), int(350 * self._scale), int(100 * self._scale)) for i in range(len(FOOD_DATA) / 4): FOOD.append([FOOD_DATA[i * 4 + NAME], FOOD_DATA[i * 4 + CALS], FOOD_DATA[i * 4 + GROUP], FOOD_DATA[i * 4 + IMAGE]]) self.food_cards.append(None) self._picture_cards.append(None) for j in range(6): self._small_picture_cards.append(None) self.allocate_food(0) x = 10 dx, dy = self.food_cards[0].get_dimensions() y = 10 for i in range(len(MYPLATE)): self.word_card_append(self._group_cards, self.pixbuf) self._group_cards[-1].type = i self._group_cards[-1].set_label(MYPLATE[i][0]) self._group_cards[-1].move((x, y)) y += int(dy * 1.25) y = 10 for i in range(len(QUANTITIES)): self.word_card_append(self._quantity_cards, self.pixbuf) self._quantity_cards[-1].type = i self._quantity_cards[-1].set_label(QUANTITIES[i]) self._quantity_cards[-1].move((x, y)) y += int(dy * 1.25) y = 10 for i in range(len(BALANCE)): self.word_card_append(self._balance_cards, self.pixbuf) self._balance_cards[-1].type = i self._balance_cards[-1].set_label(BALANCE[i]) self._balance_cards[-1].move((x, y)) y += int(dy * 1.25) self._smile = Sprite(self._sprites, int(self._width / 4), int(self._height / 4), GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'correct.png'), int(self._width / 2), int(self._height / 2))) self._smile.set_label_attributes(36) self._smile.set_margins(10, 0, 10, 0) self._frown = Sprite(self._sprites, int(self._width / 4), int(self._height / 4), GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'wrong.png'), int(self._width / 2), int(self._height / 2))) self._frown.set_label_attributes(36) self._frown.set_margins(10, 0, 10, 0) self.build_food_groups() self._all_clear()
class Game(): def __init__(self, canvas, parent=None, path=None): self._canvas = canvas self._parent = parent self._parent.show_all() self._path = path self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() self._scale = self._width / 1200. self._target = 0 self._tries = 0 self.level = 0 self._picture_cards = [] self._small_picture_cards = [] self.food_cards = [] self._group_cards = [] self._quantity_cards = [] self._balance_cards = [] self._last_twenty = [] self._background = None # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._background = Sprite( self._sprites, 0, 0, GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images','background.png'), self._width, self._height)) self._background.set_layer(0) self._background.type = None self._background.hide() self.pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'word-box.png'), int(350 * self._scale), int(100 * self._scale)) for i in range(len(FOOD_DATA) / 4): FOOD.append([FOOD_DATA[i * 4 + NAME], FOOD_DATA[i * 4 + CALS], FOOD_DATA[i * 4 + GROUP], FOOD_DATA[i * 4 + IMAGE]]) self.food_cards.append(None) self._picture_cards.append(None) for j in range(6): self._small_picture_cards.append(None) self.allocate_food(0) x = 10 dx, dy = self.food_cards[0].get_dimensions() y = 10 for i in range(len(MYPLATE)): self.word_card_append(self._group_cards, self.pixbuf) self._group_cards[-1].type = i self._group_cards[-1].set_label(MYPLATE[i][0]) self._group_cards[-1].move((x, y)) y += int(dy * 1.25) y = 10 for i in range(len(QUANTITIES)): self.word_card_append(self._quantity_cards, self.pixbuf) self._quantity_cards[-1].type = i self._quantity_cards[-1].set_label(QUANTITIES[i]) self._quantity_cards[-1].move((x, y)) y += int(dy * 1.25) y = 10 for i in range(len(BALANCE)): self.word_card_append(self._balance_cards, self.pixbuf) self._balance_cards[-1].type = i self._balance_cards[-1].set_label(BALANCE[i]) self._balance_cards[-1].move((x, y)) y += int(dy * 1.25) self._smile = Sprite(self._sprites, int(self._width / 4), int(self._height / 4), GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'correct.png'), int(self._width / 2), int(self._height / 2))) self._smile.set_label_attributes(36) self._smile.set_margins(10, 0, 10, 0) self._frown = Sprite(self._sprites, int(self._width / 4), int(self._height / 4), GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'wrong.png'), int(self._width / 2), int(self._height / 2))) self._frown.set_label_attributes(36) self._frown.set_margins(10, 0, 10, 0) self.build_food_groups() self._all_clear() def allocate_food(self, i): self.picture_append(os.path.join(self._path, 'images', FOOD_DATA[i * 4 + IMAGE]), i) self.small_picture_append(os.path.join(self._path, 'images', FOOD_DATA[i * 4 + IMAGE]), i) self.word_card_append(self.food_cards, self.pixbuf, i) self.food_cards[i].type = i self.food_cards[i].set_label(FOOD_DATA[i * 4 + NAME]) def word_card_append(self, card_list, pixbuf, i=-1): if i == -1: card_list.append(Sprite(self._sprites, 10, 10, pixbuf)) else: card_list[i] = Sprite(self._sprites, 10, 10, pixbuf) card_list[i].set_label_attributes(36) card_list[i].set_margins(10, 0, 10, 0) card_list[i].hide() def picture_append(self, path, i=-1): spr = Sprite( self._sprites, int(self._width / 2.), int(self._height / 4.), GdkPixbuf.Pixbuf.new_from_file_at_size( path, int(self._width / 3.), int(9 * self._width / 12.))) if i == -1: self._picture_cards.append(spr) else: self._picture_cards[i] = spr self._picture_cards[i].type = 'picture' self._picture_cards[i].hide() def small_picture_append(self, path, i=-1): x = int(self._width / 3.) y = int(self._height / 6.) pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( path, int(self._width / 6.), int(3 * self._width / 8.)) for j in range(6): # up to 6 of each card if i == -1: self._small_picture_cards.append(Sprite( self._sprites, x, y, pixbuf)) self._small_picture_cards[-1].type = 'picture' self._small_picture_cards[-1].hide() else: self._small_picture_cards[i * 6 + j] = Sprite( self._sprites, x, y, pixbuf) self._small_picture_cards[i * 6 + j].type = 'picture' self._small_picture_cards[i * 6 + j].hide() x += int(self._width / 6.) if j == 2: x = int(self._width / 3.) y += int(3 * self._width / 16.) def _all_clear(self): ''' Things to reinitialize when starting up a new game. ''' for p in self._picture_cards: if p is not None: p.hide() for p in self._small_picture_cards: if p is not None: p.hide() for i, w in enumerate(self.food_cards): if w is not None: w.set_label_color('black') w.set_label(FOOD[i][NAME]) w.hide() for i, w in enumerate(self._group_cards): w.set_label_color('black') w.set_label(MYPLATE[i][0]) w.hide() for i, w in enumerate(self._quantity_cards): w.set_label_color('black') w.set_label(QUANTITIES[i]) w.hide() for i, w in enumerate(self._balance_cards): w.set_label_color('black') w.set_label(BALANCE[i]) w.hide() self._smile.hide() self._frown.hide() self._background.set_layer(1) def build_food_groups(self): self._my_plate = [[], [], [], []] for i, food in enumerate(FOOD): self._my_plate[MYPLATE[food[GROUP]][QUANT]].append(i) def new_game(self): ''' Start a new game. ''' games = {0: self._name_that_food, 1: self._name_that_food_group, 2: self._compare_calories, 3: self._how_much_to_eat, 4: self._balanced_meal} self._all_clear() games[self.level]() self._frown.set_label('') self._smile.set_label('') self._tries = 0 def _name_that_food(self): ''' Choose food cards and one matching food picture ''' x = 10 y = 10 dx, dy = self.food_cards[0].get_dimensions() # Select some cards word_list = [] for i in range(NCARDS): j = int(uniform(0, len(FOOD))) while j in word_list: j = int(uniform(0, len(FOOD))) word_list.append(j) # Show the word cards from the list for i in word_list: if self.food_cards[i] is None: self.allocate_food(i) self.food_cards[i].set_layer(100) self.food_cards[i].move((x, y)) y += int(dy * 1.25) # Choose a random food image from the list and show it. self._target = self.food_cards[ word_list[int(uniform(0, NCARDS))]].type while self._target in self._last_twenty: self._target = self.food_cards[ word_list[int(uniform(0, NCARDS))]].type self._last_twenty.append(self._target) if len(self._last_twenty) > 20: self._last_twenty.remove(self._last_twenty[0]) self._picture_cards[self._target].set_layer(100) def _name_that_food_group(self): ''' Show group cards and one food picture ''' for i in range(len(MYPLATE)): self._group_cards[i].set_layer(100) # Choose a random food image and show it. self._target = int(uniform(0, len(FOOD))) if self.food_cards[self._target] is None: self.allocate_food(self._target) self._picture_cards[self._target].set_layer(100) def _compare_calories(self): ''' Choose food cards and compare the calories ''' x = 10 y = 10 dx, dy = self.food_cards[0].get_dimensions() # Select some cards word_list = [] for i in range(6): j = int(uniform(0, len(FOOD))) while j in word_list: j = int(uniform(0, len(FOOD))) word_list.append(j) if self.food_cards[j] is None: self.allocate_food(j) # Show the word cards from the list for i in word_list: self.food_cards[i].set_layer(100) self.food_cards[i].move((x, y)) y += int(dy * 1.25) # Show food images self._target = word_list[0] for i in range(5): if FOOD[word_list[i + 1]][CALS] > FOOD[self._target][CALS]: self._target = word_list[i + 1] self._small_picture_cards[word_list[0] * 6].set_layer(100) self._small_picture_cards[word_list[1] * 6 + 1].set_layer(100) self._small_picture_cards[word_list[2] * 6 + 2].set_layer(100) self._small_picture_cards[word_list[3] * 6 + 3].set_layer(100) self._small_picture_cards[word_list[4] * 6 + 4].set_layer(100) self._small_picture_cards[word_list[5] * 6 + 5].set_layer(100) def _how_much_to_eat(self): ''' Show quantity cards and one food picture ''' for i in range(len(QUANTITIES)): self._quantity_cards[i].set_layer(100) # Choose a random image from the list and show it. self._target = int(uniform(0, len(FOOD))) if self.food_cards[self._target] is None: self.allocate_food(self._target) self._picture_cards[self._target].set_layer(100) def _balanced_meal(self): ''' A well-balanced meal ''' for i in range(2): self._balance_cards[i].set_layer(100) # Determine how many foods from each group n = [0, 0, 0, 0] n[0] = int(uniform(0, 2.5)) n[1] = int(uniform(0, 3 - n[0])) n[2] = 3 - n[0] - n[1] n[3] = 6 - n[0] - n[1] - n[2] # Fill a plate with foods from different groups meal = [] for i in range(n[0]): # Sweets j = int(uniform(0, len(self._my_plate[0]))) meal.append(self._my_plate[0][j]) for i in range(n[1]): # Dairy j = int(uniform(0, len(self._my_plate[1]))) meal.append(self._my_plate[1][j]) for i in range(n[2]): # Protein and Fruits j = int(uniform(0, len(self._my_plate[2]))) meal.append(self._my_plate[2][j]) for i in range(n[3]): # Veggies and Grains j = int(uniform(0, len(self._my_plate[3]))) meal.append(self._my_plate[3][j]) if n[0] < 2 and n[1] < 2 and n[2] < n[3]: self._target = 0 # Balanced meal else: self._target = 1 for i in range(6): if self.food_cards[meal[i]] is None: self.allocate_food(meal[i]) # Randomly position small cards self._small_picture_cards[meal[3] * 6].set_layer(100) self._small_picture_cards[meal[4] * 6 + 1].set_layer(100) self._small_picture_cards[meal[1] * 6 + 2].set_layer(100) self._small_picture_cards[meal[2] * 6 + 3].set_layer(100) self._small_picture_cards[meal[5] * 6 + 4].set_layer(100) self._small_picture_cards[meal[0] * 6 + 5].set_layer(100) def _button_press_cb(self, win, event): win.grab_focus() x, y = map(int, event.get_coords()) spr = self._sprites.find_sprite((x, y)) if spr == None: return # We only care about clicks on word cards if type(spr.type) != int: return # Which card was clicked? Set its label to red. spr.set_label_color('red') label = spr.labels[0] spr.set_label(label) if self.level == 0: if spr.type == self._target: self._smile.set_layer(200) self._tries = 3 else: self._frown.set_layer(200) self._tries += 1 if self._tries == 3: self.food_cards[self._target].set_label_color('blue') label = self.food_cards[self._target].labels[0] self.food_cards[self._target].set_label(label) elif self.level == 1: i = FOOD[self._target][GROUP] if spr.type == i: self._smile.set_layer(200) self._tries = 3 else: self._frown.set_layer(200) self._tries += 1 if self._tries == 3: self._group_cards[i].set_label_color('blue') label = self._group_cards[i].labels[0] self._group_cards[i].set_label(label) elif self.level == 2: if spr.type == self._target: self._smile.set_layer(200) self._tries = 3 else: self._frown.set_layer(200) self._tries += 1 if self._tries == 3: self.food_cards[self._target].set_label_color('blue') label = self.food_cards[self._target].labels[0] self.food_cards[self._target].set_label(label) elif self.level == 3: i = MYPLATE[FOOD[self._target][GROUP]][QUANT] if spr.type == i: self._smile.set_layer(200) self._tries = 3 else: self._frown.set_layer(200) self._tries += 1 if self._tries == 3: self._quantity_cards[i].set_label_color('blue') label = self._quantity_cards[i].labels[0] self._quantity_cards[i].set_label(label) elif self.level == 4: if self._target == spr.type: self._smile.set_layer(200) self._tries = 3 else: self._frown.set_layer(200) self._tries += 1 if self._tries == 3: self._balance_cards[self._target].set_label_color('blue') label = self._balance_cards[self._target].labels[0] self._balance_cards[self._target].set_label(label) else: _logger.debug('unknown play level %d' % (self.level)) # Play again if self._tries == 3: GObject.timeout_add(2000, self.new_game) else: GObject.timeout_add(1000, self._reset_game) return True def _reset_game(self): self._frown.hide() if self.level in [0, 2]: for i, w in enumerate(self.food_cards): w.set_label_color('black') w.set_label(FOOD[i][NAME]) elif self.level == 1: for i, w in enumerate(self._group_cards): w.set_label_color('black') w.set_label(MYPLATE[i][0]) elif self.level == 3: for i, w in enumerate(self._quantity_cards): w.set_label_color('black') w.set_label(QUANTITIES[i]) elif self.level == 4: for i, w in enumerate(self._balance_cards): w.set_label_color('black') w.set_label(BALANCE[i]) def __draw_cb(self, canvas, cr): self._sprites.redraw_sprites(cr=cr) def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self._canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit()
class Game: def __init__(self, canvas, parent=None, path=None, colors=["#A0FFA0", "#FF8080"]): self._canvas = canvas self._parent = parent self._parent.show_all() self._path = path self._colors = ["#FFFFFF"] self._colors.append(colors[0]) self._colors.append(colors[1]) self._canvas.set_can_focus(True) self._canvas.connect("expose-event", self._expose_cb) self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._height / (4 * DOT_SIZE * 1.3) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.0) self.we_are_sharing = False self._start_time = 0 self._timeout_id = None self._level = 3 self._game = 0 self._correct = 0 # Find the image files self._PATHS = glob.glob(os.path.join(self._path, "images", "*.png")) self._CPATHS = glob.glob(os.path.join(self._path, "color-images", "*.svg")) # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] self._opts = [] yoffset = int(self._space / 2.0) self._line = Sprite( self._sprites, 0, int(3 * (self._dot_size + self._space) + yoffset / 2.0), self._line(vertical=False) ) for y in range(3): for x in range(6): xoffset = int((self._width - 6 * self._dot_size - 5 * self._space) / 2.0) self._dots.append( Sprite( self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space) + yoffset, self._new_dot_surface(color=self._colors[0]), ) ) self._dots[-1].type = -1 # No image self._dots[-1].set_label_attributes(72) y = 3 for x in range(3): self._opts.append( Sprite( self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space) + yoffset, self._new_dot_surface(color=self._colors[0]), ) ) self._opts[-1].type = -1 # No image self._opts[-1].set_label_attributes(72) self._opts[-1].hide() def _all_clear(self): """ Things to reinitialize when starting up a new game. """ if self._timeout_id is not None: GObject.source_remove(self._timeout_id) # Auto advance levels if self._correct > 3 and self._level < len(self._dots): self._level += 3 self._correct = 0 self._set_label("") for i in range(3): self._opts[i].hide() self._opts[i].type = -1 self._opts[i].set_label("") for dot in self._dots: dot.type = -1 if self._game == 2 or self._dots.index(dot) < self._level: dot.set_shape(self._new_dot_surface(self._colors[abs(dot.type)])) dot.set_label("?") dot.set_layer(100) else: dot.hide() self._dance_counter = 0 self._dance_step() def _dance_step(self): """ Short animation before loading new game """ if self._game == 2: for i in range(len(self._dots)): self._dots[i].set_shape(self._new_dot_surface(self._colors[int(uniform(0, 3))])) else: for i in range(self._level): self._dots[i].set_shape(self._new_dot_surface(self._colors[int(uniform(0, 3))])) self._dance_counter += 1 if self._dance_counter < 10: self._timeout_id = GObject.timeout_add(500, self._dance_step) else: self._new_game() def new_game(self, game=None, restart=True): """ Start a new game. """ if game is not None: self._game = game self._level = 3 self._correct = 0 if restart: self._all_clear() def _image_in_dots(self, n): for i in range(self._level): if self._dots[i].type == n: return True return False def _image_in_opts(self, n): for i in range(3): if self._opts[i].type == n: return True return False def _choose_random_images(self): """ Choose images at random """ if self._game == 3: maxi = len(self._CPATHS) else: maxi = len(self._PATHS) for i in range(self._level): if self._dots[i].type == -1: n = int(uniform(0, maxi)) while self._image_in_dots(n): n = int(uniform(0, maxi)) self._dots[i].type = n if self._game == 3: self._dots[i].set_shape(self._new_dot_surface(color_image=self._dots[i].type)) else: self._dots[i].set_shape(self._new_dot_surface(image=self._dots[i].type)) self._dots[i].set_layer(100) self._dots[i].set_label("") def _load_image_from_list(self): if self._recall_counter == len(self._recall_list): self._timeout_id = GObject.timeout_add(1000, self._ask_the_question) return for dot in self._dots: dot.type = self._recall_list[self._recall_counter] dot.set_shape(self._new_dot_surface(image=dot.type)) dot.set_layer(100) dot.set_label("") self._recall_counter += 1 self._timeout_id = GObject.timeout_add(1000, self._load_image_from_list) def _find_repeat(self): """ Find an image that repeats """ for i in range(self._level): for j in range(self._level - i - 1): if self._dots[i].type == self._dots[j].type: return i return None def _new_game(self, restore=False): """ Load game images and then ask a question... """ if self._game in [0, 1, 3]: self._choose_random_images() else: # game 2 # generate a random list self._recall_list = [] for i in range(12): n = int(uniform(0, len(self._PATHS))) while n in self._recall_list: n = int(uniform(0, len(self._PATHS))) self._recall_list.append(n) self._recall_counter = 0 self._load_image_from_list() if self._game == 0: if not restore: # Repeat at least one of the images self._repeat = int(uniform(0, self._level)) n = (self._repeat + int(uniform(1, self._level))) % self._level _logger.debug("repeat=%d, n=%d" % (self._repeat, n)) self._dots[self._repeat].set_shape(self._new_dot_surface(image=self._dots[n].type)) self._dots[self._repeat].type = self._dots[n].type else: # Find repeated image, as that is the answer self._repeat = self._find_repeat() if self._repeat is None: _logger.debug("could not find repeat") self._repeat = 0 if self.we_are_sharing: _logger.debug("sending a new game") self._parent.send_new_game() if self._game in [0, 1, 3]: self._timeout_id = GObject.timeout_add(3000, self._ask_the_question) def _ask_the_question(self): """ Each game has a challenge """ self._timeout_id = None # Hide the dots if self._game == 2: for dot in self._dots: dot.hide() else: for i in range(self._level): self._dots[i].hide() if self._game == 0: self._set_label(_("Recall which image was repeated.")) # Show the possible solutions for i in range(3): n = int(uniform(0, len(self._PATHS))) if self._level == 3: while n == self._dots[self._repeat].type or self._image_in_opts(n): n = int(uniform(0, len(self._PATHS))) else: while n == self._dots[self._repeat].type or not self._image_in_dots(n) or self._image_in_opts(n): n = int(uniform(0, len(self._PATHS))) self._opts[i].type = n self._answer = int(uniform(0, 3)) self._opts[self._answer].type = self._dots[self._repeat].type for i in range(3): self._opts[i].set_shape(self._new_dot_surface(image=self._opts[i].type)) self._opts[i].set_layer(100) elif self._game == 1: self._set_label(_("Recall which image was not shown.")) # Show the possible solutions for i in range(3): n = int(uniform(0, len(self._PATHS))) while not self._image_in_dots(n) or self._image_in_opts(n): n = int(uniform(0, len(self._PATHS))) self._opts[i].type = n self._answer = int(uniform(0, 3)) n = int(uniform(0, len(self._PATHS))) while self._image_in_dots(n): n = int(uniform(0, len(self._PATHS))) self._opts[self._answer].type = n for i in range(3): self._opts[i].set_shape(self._new_dot_surface(image=self._opts[i].type)) self._opts[i].set_layer(100) elif self._game == 3: self._set_label(_("Recall which image was not shown.")) # Show the possible solutions for i in range(3): n = int(uniform(0, len(self._CPATHS))) while not self._image_in_dots(n) or self._image_in_opts(n): n = int(uniform(0, len(self._CPATHS))) self._opts[i].type = n self._answer = int(uniform(0, 3)) n = int(uniform(0, len(self._CPATHS))) while self._image_in_dots(n): n = int(uniform(0, len(self._CPATHS))) self._opts[self._answer].type = n for i in range(3): self._opts[i].set_shape(self._new_dot_surface(color_image=self._opts[i].type)) self._opts[i].set_layer(100) elif self._game == 2: self._set_label( ngettext( "Recall which image was displayed %d time ago", "Recall which image was displayed %d times ago", (int(self._level / 3)), ) % (int(self._level / 3)) ) # Show the possible solutions for i in range(3): self._answer = len(self._recall_list) - int(self._level / 3) - 1 n = int(uniform(0, len(self._recall_list))) while n == self._answer: n = int(uniform(0, len(self._recall_list))) self._opts[i].type = n i = int(uniform(0, 3)) self._opts[i].type = self._recall_list[self._answer] for i in range(3): self._opts[i].set_shape(self._new_dot_surface(image=self._opts[i].type)) self._opts[i].set_layer(100) def restore_game(self, dot_list, correct=0, level=3, game=0): """ Restore a game from the Journal or share """ # TODO: Save/restore recall list for game 2 self._correct = correct self._level = level self._game = game for i, dot in enumerate(dot_list): self._dots[i].type = dot if dot == -1: self._dots[i].hide() self._new_game(restore=True) def save_game(self): """ Return dot list for saving to Journal or sharing """ dot_list = [] for dot in self._dots: dot_list.append(dot.type) return dot_list, self._correct, self._level, self._game def _set_label(self, string): """ Set the label in the toolbar or the window frame. """ self._parent.status.set_label(string) def _button_press_cb(self, win, event): if self._timeout_id is not None: _logger.debug("still in timeout... ignoring click") return win.grab_focus() x, y = map(int, event.get_coords()) spr = self._sprites.find_sprite((x, y), inverse=True) if spr == None: return if self._game in [0, 1, 3]: for i in range(3): if self._opts[i] == spr: break self._opts[i].set_shape(self._new_dot_surface(color=self._colors[0])) if i == self._answer: self._opts[i].set_label("☻") self._correct += 1 else: self._opts[i].set_label("☹") self._correct = 0 else: for i in range(3): if self._opts[i] == spr: break self._opts[i].set_shape(self._new_dot_surface(color=self._colors[0])) if self._opts[i].type == self._recall_list[self._answer]: self._opts[i].set_label("☻") self._correct += 1 else: self._opts[i].set_label("☹") self._correct = 0 if self._game in [0, 1, 3]: for i in range(self._level): self._dots[i].set_layer(100) else: for dot in self._dots: dot.set_shape(self._new_dot_surface(image=self._recall_list[self._answer])) dot.set_layer(100) if self._correct == 0: self._timeout_id = GObject.timeout_add(5000, self.new_game) else: self._timeout_id = GObject.timeout_add(3000, self.new_game) return True def remote_button_press(self, dot, color): """ Receive a button press from a sharer """ self._dots[dot].type = color self._dots[dot].set_shape(self._new_dot_surface(color=self._colors[color])) def set_sharing(self, share=True): _logger.debug("enabling sharing") self.we_are_sharing = share def _expose_cb(self, win, event): self.do_expose_event(event) def do_expose_event(self, event): """ Handle the expose-event by drawing """ # Restrict Cairo to the exposed area cr = self._canvas.get_window().cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit() def _new_dot_surface(self, color="#000000", image=None, color_image=None): """ generate a dot of a color color """ self._dot_cache = {} if color_image is not None: if color_image + 10000 in self._dot_cache: return self._dot_cache[color_image + 10000] pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, self._CPATHS[color_image]), self._svg_width, self._svg_height ) elif image is not None: if image in self._dot_cache: return self._dot_cache[image] pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, self._PATHS[image]), self._svg_width, self._svg_height ) else: if color in self._dot_cache: return self._dot_cache[color] self._stroke = color self._fill = color self._svg_width = self._dot_size self._svg_height = self._dot_size i = self._colors.index(color) pixbuf = svg_str_to_pixbuf( self._header() + self._circle(self._dot_size / 2.0, self._dot_size / 2.0, self._dot_size / 2.0) + self._footer() ) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self._svg_width, self._svg_height) context = cairo.Context(surface) context = Gdk.CairoContext(context) context.set_source_pixbuf(pixbuf, 0, 0) context.rectangle(0, 0, self._svg_width, self._svg_height) context.fill() if color_image is not None: self._dot_cache[color_image + 10000] = surface elif image is not None: self._dot_cache[image] = surface else: self._dot_cache[color] = surface return surface def _line(self, vertical=True): """ Generate a center line """ if vertical: self._svg_width = 3 self._svg_height = self._height return svg_str_to_pixbuf(self._header() + self._rect(3, self._height, 0, 0) + self._footer()) else: self._svg_width = self._width self._svg_height = 3 return svg_str_to_pixbuf(self._header() + self._rect(self._width, 3, 0, 0) + self._footer()) def _header(self): return ( "<svg\n" + 'xmlns:svg="http://www.w3.org/2000/svg"\n' + 'xmlns="http://www.w3.org/2000/svg"\n' + 'xmlns:xlink="http://www.w3.org/1999/xlink"\n' + 'version="1.1"\n' + 'width="' + str(self._svg_width) + '"\n' + 'height="' + str(self._svg_height) + '">\n' ) def _rect(self, w, h, x, y): svg_string = " <rect\n" svg_string += ' width="%f"\n' % (w) svg_string += ' height="%f"\n' % (h) svg_string += ' rx="%f"\n' % (0) svg_string += ' ry="%f"\n' % (0) svg_string += ' x="%f"\n' % (x) svg_string += ' y="%f"\n' % (y) svg_string += 'style="fill:#000000;stroke:#000000;"/>\n' return svg_string def _circle(self, r, cx, cy): return ( '<circle style="fill:' + str(self._fill) + ";stroke:" + str(self._stroke) + ';" r="' + str(r - 0.5) + '" cx="' + str(cx) + '" cy="' + str(cy) + '" />\n' ) def _footer(self): return "</svg>\n"
class Game(): def __init__(self, canvas, parent=None, path=None, colors=['#A0FFA0', '#FF8080']): self._canvas = canvas self._parent = parent self._parent.show_all() self._path = path self.level = 1 self._colors = ['#FFFFFF'] self._colors.append(colors[0]) self._colors.append(colors[1]) self._colors.append(colors[0]) self._colors.append('#FF0000') self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - GRID_CELL_SIZE if self._width < self._height: self.portrait = True self.grid_height = TEN self.grid.width = SEVEN else: self.portrait = False self.grid_height = SEVEN self.grid_width = TEN self._scale = min(self._width / (self.grid_width * DOT_SIZE * 1.2), self._height / (self.grid_height * DOT_SIZE * 1.2)) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self.we_are_sharing = False # '-1' Workaround for showing 'second 0' self._game_time_seconds = -1 self._game_time = "00:00" self._timeout_id = None # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] for y in range(self.grid_height): for x in range(self.grid_width): xoffset = int((self._width - self.grid_width * self._dot_size - (self.grid_width - 1) * self._space) / 2.) self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space), self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set self._dots[-1].set_label_attributes(40) self._all_clear() Gdk.Screen.get_default().connect('size-changed', self._configure_cb) def _configure_cb(self, event): dot_list = self.save_game() self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - GRID_CELL_SIZE if self._width < self._height: self.portrait = True self.grid_height = TEN self.grid_width = SEVEN else: self.portrait = False self.grid_height = SEVEN self.grid_width = TEN i = 0 for y in range(self.grid_height): for x in range(self.grid_width): xoffset = int((self._width - self.grid_width * self._dot_size - (self.grid_width - 1) * self._space) / 2.) self._dots[i].move( (xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space))) i += 1 self.restore_game(dot_list) def __draw_cb(self, canvas, cr): self._sprites.redraw_sprites(cr=cr) def _all_clear(self): ''' Things to reinitialize when starting up a new game. ''' for dot in self._dots: if dot.type != 1: dot.type = 1 dot.set_shape(self._new_dot(self._colors[dot.type])) dot.set_label('') self._stop_timer() def new_game(self): ''' Start a new game. ''' self._all_clear() # Fill in a few dots to start for i in range(self.level): n = int(uniform(0, self.grid_width * self.grid_height)) while True: if self._dots[n].type == 1: self._dots[n].type = 2 self._dots[n].set_shape(self._new_dot(self._colors[1])) break else: n = int(uniform(0, self.grid_width * self.grid_height)) if self.we_are_sharing: _logger.debug('sending a new game') self._parent.send_new_game() self._start_timer() def restore_game(self, dot_list): ''' Restore a game from the Journal or share ''' for i, dot in enumerate(dot_list): self._dots[i].type = dot if dot in [4]: # marked by user self._dots[i].set_shape(self._new_dot(self._colors[2])) elif dot in [1, 2]: # unmarked self._dots[i].set_shape(self._new_dot(self._colors[1])) else: # revealed by user self._dots[i].set_shape(self._new_dot(self._colors[0])) for i, dot in enumerate(dot_list): if dot == 0: # label with count count = self._count([2, 4], self._dots[i]) if count > 0: self._dots[i].set_label(count) self._counter() def save_game(self): ''' Return dot list for saving to Journal or sharing ''' dot_list = [] for dot in self._dots: dot_list.append(dot.type) return dot_list def _set_label(self, gametime): ''' Set the label in the toolbar or the window frame. ''' self._parent.status.set_label(_('Level') + ' ' + str(self.level) + ' / ' + gametime) def _neighbors(self, spr): ''' Return the list of surrounding dots ''' neighbors = [] x, y = self._dot_to_grid(self._dots.index(spr)) if x > 0 and y > 0: neighbors.append(self._dots[self._grid_to_dot((x - 1, y - 1))]) if x > 0: neighbors.append(self._dots[self._grid_to_dot((x - 1, y))]) if x > 0 and y < self.grid_height - 1: neighbors.append(self._dots[self._grid_to_dot((x - 1, y + 1))]) if y > 0: neighbors.append(self._dots[self._grid_to_dot((x, y - 1))]) if y < self.grid_height - 1: neighbors.append(self._dots[self._grid_to_dot((x, y + 1))]) if x < self.grid_width - 1 and y > 0: neighbors.append(self._dots[self._grid_to_dot((x + 1, y - 1))]) if x < self.grid_width - 1: neighbors.append(self._dots[self._grid_to_dot((x + 1, y))]) if x < self.grid_width - 1 and y < self.grid_height - 1: neighbors.append(self._dots[self._grid_to_dot((x + 1, y + 1))]) return neighbors def _count(self, count_type, spr): ''' Count the number of surrounding dots of type count_type ''' counter = 0 for dot in self._neighbors(spr): if dot.type in count_type: counter += 1 return counter def _floodfill(self, old_type, spr): if spr.type not in old_type: return spr.type = 0 spr.set_shape(self._new_dot(self._colors[spr.type])) if self.we_are_sharing: _logger.debug('sending a click to the share') self._parent.send_dot_click(self._dots.index(spr), spr.type) counter = self._count([2, 4], spr) if counter > 0: spr.set_label(str(counter)) else: spr.set_label('') for dot in self._neighbors(spr): self._floodfill(old_type, dot) def _button_press_cb(self, win, event): win.grab_focus() x, y = map(int, event.get_coords()) spr = self._sprites.find_sprite((x, y)) if spr is None: return if event.button > 1: # right click if spr.type != 0: self._flip_the_cookie(spr) return True else: if spr.type != 0: red, green, blue, alpha = spr.get_pixel((x, y)) if red > 190 and red < 215: # clicked the cookie self._flip_the_cookie(spr) return True if spr.type in [2, 4]: spr.set_shape(self._new_dot(self._colors[4])) self._frown() return True if spr.type is not None: self._floodfill([1, 3], spr) self._test_game_over() return True def _flip_the_cookie(self, spr): if spr.type in [1, 2]: spr.set_shape(self._new_dot(self._colors[2])) spr.type += 2 else: # elif spr.type in [3, 4]: spr.set_shape(self._new_dot(self._colors[1])) spr.type -= 2 self._test_game_over() def remote_button_press(self, dot, color): ''' Receive a button press from a sharer ''' self._dots[dot].type = color self._dots[dot].set_shape(self._new_dot(self._colors[color])) def set_sharing(self, share=True): _logger.debug('enabling sharing') self.we_are_sharing = share def _counter(self): ''' Display game_time as hours:minutes:seconds. ''' self._game_time_seconds += 1 self._game_time = convert_seconds_to_minutes(self._game_time_seconds) self._set_label(self._game_time) self._timeout_id = GLib.timeout_add(1000, self._counter) def _start_timer(self): ''' Start/reset the timer ''' # '-1' Workaround for showing 'second 0' self._game_time_seconds = -1 self._game_time = "00:00" self._timeout_id = None self._counter() def _stop_timer(self): if self._timeout_id is not None: GLib.source_remove(self._timeout_id) self._timeout_id = None def _smile(self): self._stop_timer() self.game_won = True for dot in self._dots: if dot.type == 0: dot.set_label('☻') self._new_game_alert() def _frown(self): self._stop_timer() self.game_won = False for dot in self._dots: if dot.type == 0: dot.set_label('☹') self._new_game_alert() def _test_game_over(self): ''' Check to see if game is over ''' for dot in self._dots: if dot.type == 1 or dot.type == 2: return False self._parent.all_scores.append(self._game_time) _logger.debug(self._parent.all_scores) self._smile() return True def _grid_to_dot(self, pos): ''' calculate the dot index from a column and row in the grid ''' return pos[0] + pos[1] * self.grid_width def _dot_to_grid(self, dot): ''' calculate the grid column and row for a dot ''' return [dot % self.grid_width, int(dot / self.grid_width)] def _new_game_alert(self): alert = Alert() alert.props.title = _('New game') alert.props.msg = _('Do you want to play a new game?') icon = Icon(icon_name='dialog-cancel') alert.add_button(Gtk.ResponseType.CANCEL, _('Cancel'), icon) icon.show() ok_icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.OK, _('New game'), ok_icon) ok_icon.show() alert.connect('response', self.__game_alert_response_cb) self._parent.add_alert(alert) alert.show() def __game_alert_response_cb(self, alert, response_id): self._parent.remove_alert(alert) if response_id is Gtk.ResponseType.OK: if self.game_won == False: self.level = 1 elif self.grid_height * self.grid_width - self.level > 1: self.level += 1 self.new_game() def _expose_cb(self, win, event): self.do_expose_event(event) def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self._canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit() def _new_dot(self, color): ''' generate a dot of a color color ''' self._dot_cache = {} if color not in self._dot_cache: self._stroke = color self._fill = color self._svg_width = self._dot_size self._svg_height = self._dot_size i = self._colors.index(color) if PATHS[i] is False: pixbuf = svg_str_to_pixbuf( self._header() + self._circle(self._dot_size / 2., self._dot_size / 2., self._dot_size / 2.) + self._footer()) else: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, PATHS[i]), self._svg_width, self._svg_height) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self._svg_width, self._svg_height) context = cairo.Context(surface) Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0) context.rectangle(0, 0, self._svg_width, self._svg_height) context.fill() self._dot_cache[color] = surface return self._dot_cache[color] def _line(self, vertical=True): ''' Generate a center line ''' if vertical: self._svg_width = 3 self._svg_height = self._height return svg_str_to_pixbuf( self._header() + self._rect(3, self._height, 0, 0) + self._footer()) else: self._svg_width = self._width self._svg_height = 3 return svg_str_to_pixbuf( self._header() + self._rect(self._width, 3, 0, 0) + self._footer()) def _header(self): return '<svg\n' + 'xmlns:svg="http://www.w3.org/2000/svg"\n' + \ 'xmlns="http://www.w3.org/2000/svg"\n' + \ 'xmlns:xlink="http://www.w3.org/1999/xlink"\n' + \ 'version="1.1"\n' + 'width="' + str(self._svg_width) + '"\n' + \ 'height="' + str(self._svg_height) + '">\n' def _rect(self, w, h, x, y): svg_string = ' <rect\n' svg_string += ' width="%f"\n' % (w) svg_string += ' height="%f"\n' % (h) svg_string += ' rx="%f"\n' % (0) svg_string += ' ry="%f"\n' % (0) svg_string += ' x="%f"\n' % (x) svg_string += ' y="%f"\n' % (y) svg_string += 'style="fill:#000000;stroke:#000000;"/>\n' return svg_string def _circle(self, r, cx, cy): return '<circle style="fill:' + str(self._fill) + ';stroke:' + \ str(self._stroke) + ';" r="' + str(r - 0.5) + '" cx="' + \ str(cx) + '" cy="' + str(cy) + '" />\n' def _footer(self): return '</svg>\n'
def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = [colors[0]] self._colors.append(colors[1]) self._colors.append('#FFFFFF') self._colors.append('#000000') self._colors.append('#FF0000') self._colors.append('#FF8000') self._colors.append('#FFFF00') self._colors.append('#00FF00') self._colors.append('#00FFFF') self._colors.append('#0000FF') self._colors.append('#FF00FF') self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK) self._canvas.add_events(Gdk.EventMask.POINTER_MOTION_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._canvas.connect("button-release-event", self._button_release_cb) self._canvas.connect("motion-notify-event", self._mouse_move_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - GRID_CELL_SIZE scale = [self._width / (10 * DOT_SIZE * 1.2), self._height / (6 * DOT_SIZE * 1.2)] self._scale = min(scale) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self._orientation = 'horizontal' self.we_are_sharing = False self.playing_with_robot = False self._press = False self.last_spr = None self._timer = None self.roygbiv = False # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] for y in range(SIX): for x in range(TEN): xoffset = int((self._width - TEN * self._dot_size - \ (TEN - 1) * self._space) / 2.) self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space), self._new_dot(self._colors[2]))) self._dots[-1].type = 2 # not set self._dots[-1].set_label_attributes(40) self.vline = Sprite(self._sprites, int(self._width / 2.) - 1, 0, self._line(vertical=True)) n = SIX / 2. self.hline = Sprite( self._sprites, 0, int(self._dot_size * n + self._space * (n - 0.5)) - 1, self._line(vertical=False)) self.hline.hide() # and initialize a few variables we'll need. self._all_clear()
def __init__(self, canvas, parent=None, path=None, root=None, mode='array', colors=['#A0FFA0', '#FF8080']): self._canvas = canvas self._parent = parent self._path = path self._root = root self._mode = mode self.current_image = 0 self.playing = False self._timeout_id = None self._prev_mouse_pos = (0, 0) self._start_time = 0 self._colors = ['#FFFFFF'] self._colors.append(colors[0]) self._colors.append(colors[1]) self._canvas.add_events( Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.BUTTON_MOTION_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.POINTER_MOTION_HINT_MASK | Gdk.EventMask.TOUCH_MASK) self._canvas.connect('draw', self.__draw_cb) self._canvas.connect('event', self.__event_cb) self.configure(move=False) self.we_are_sharing = False self._start_time = 0 self._timeout_id = None # Find the image files self._PATHS = glob.glob(os.path.join(self._path, 'images', '*.svg')) # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) a = max(Gdk.Screen.width(), Gdk.Screen.height()) b = min(Gdk.Screen.width(), Gdk.Screen.height()) self._bg_pixbufs = [] if self._parent.tablet_mode: # text on top # landscape self._bg_pixbufs.append(svg_str_to_pixbuf(genhole( a, a, 3 * style.GRID_CELL_SIZE, style.DEFAULT_SPACING, a - 3 * style.GRID_CELL_SIZE, style.GRID_CELL_SIZE * 3 + style.DEFAULT_SPACING))) # portrait self._bg_pixbufs.append(svg_str_to_pixbuf(genhole( a, a, 3 * style.GRID_CELL_SIZE, style.DEFAULT_SPACING, b - 3 * style.GRID_CELL_SIZE, style.GRID_CELL_SIZE * 3 + style.DEFAULT_SPACING))) else: # text on bottom # landscape self._bg_pixbufs.append(svg_str_to_pixbuf(genhole( a, a, 3 * style.GRID_CELL_SIZE, b - style.GRID_CELL_SIZE * 4 - style.DEFAULT_SPACING, a - 3 * style.GRID_CELL_SIZE, b - style.GRID_CELL_SIZE - style.DEFAULT_SPACING))) # portrait self._bg_pixbufs.append(svg_str_to_pixbuf(genhole( a, a, 3 * style.GRID_CELL_SIZE, a - style.GRID_CELL_SIZE * 4 - style.DEFAULT_SPACING, b - 3 * style.GRID_CELL_SIZE, a - style.GRID_CELL_SIZE - style.DEFAULT_SPACING))) if Gdk.Screen.width() > Gdk.Screen.height(): self._bg = Sprite(self._sprites, 0, 0, self._bg_pixbufs[0]) else: self._bg = Sprite(self._sprites, 0, 0, self._bg_pixbufs[1]) self._bg.set_layer(-2) self._bg.type = 'background' size = 3 * self._dot_size + 4 * self._space x = int((Gdk.Screen.width() - size) / 2.) self._dots = [] self._Dots = [] # larger dots for linear mode X = int((Gdk.Screen.width() - self._dot_size * 3) / 2.) Y = style.GRID_CELL_SIZE + self._yoff if self._parent.tablet_mode: yoffset = self._space * 2 + self._yoff else: yoffset = self._yoff for y in range(3): for x in range(3): xoffset = int((self._width - 3 * self._dot_size - 2 * self._space) / 2.) self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space) + yoffset, self._new_dot_surface(color=self._colors[0]))) self._dots[-1].type = -1 # No image self._dots[-1].set_label_attributes(72) self._dots[-1].set_label('?') self._Dots.append( Sprite( self._sprites, X, Y, self._new_dot_surface(color=self._colors[0], large=True))) self._Dots[-1].type = -1 # No image self._Dots[-1].set_label_attributes(72 * 3) self._Dots[-1].set_label('?') self.number_of_images = len(self._PATHS) if USE_ART4APPS: self._art4apps = Art4Apps() self.number_of_images = len(self._art4apps.get_words()) self._record_pixbufs = [] for icon in ['media-audio', 'media-audio-recording']: self._record_pixbufs.append( GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._root, 'icons', icon + '.svg'), style.GRID_CELL_SIZE, style.GRID_CELL_SIZE)) self._play_pixbufs = [] for icon in ['play-inactive', 'play']: self._play_pixbufs.append( GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._root, 'icons', icon + '.svg'), style.GRID_CELL_SIZE, style.GRID_CELL_SIZE)) self._speak_pixbufs = [] for icon in ['speak-inactive', 'speak']: self._speak_pixbufs.append( GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._root, 'icons', icon + '.svg'), style.GRID_CELL_SIZE, style.GRID_CELL_SIZE)) left = style.GRID_CELL_SIZE right = Gdk.Screen.width() - 2 * style.GRID_CELL_SIZE y0 = style.DEFAULT_SPACING + style.DEFAULT_PADDING y1 = y0 + style.GRID_CELL_SIZE y2 = y1 + style.GRID_CELL_SIZE if not self._parent.tablet_mode: dy = Gdk.Screen.height() - 4 * style.GRID_CELL_SIZE - \ 2 * style.DEFAULT_SPACING y0 += dy y1 += dy y2 += dy y3 = int((Gdk.Screen.height() - 2 * style.GRID_CELL_SIZE) / 2) self._record = Sprite( self._sprites, right, y0, self._record_pixbufs[RECORD_OFF]) self._record.set_layer(1) self._record.type = 'record' self._play = Sprite( self._sprites, right, y1, self._play_pixbufs[PLAY_OFF]) self._play.set_layer(1) self._play.type = 'play-inactive' self._speak = Sprite( self._sprites, right, y2, self._speak_pixbufs[SPEAK_OFF]) self._speak.set_layer(1) self._speak.type = 'speak-inactive' self._next_prev_pixbufs = [] for icon in ['go-previous', 'go-next', 'go-previous-inactive', 'go-next-inactive']: self._next_prev_pixbufs.append( GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._root, 'icons', icon + '.svg'), style.GRID_CELL_SIZE, style.GRID_CELL_SIZE)) self._prev = Sprite( self._sprites, left, y3, self._next_prev_pixbufs[PREV_INACTIVE]) self._prev.set_layer(1) self._prev.type = 'prev' if self._mode == 'array': self._prev.hide() self._next = Sprite( self._sprites, right, y3, self._next_prev_pixbufs[NEXT]) self._next.set_layer(1) self._next.type = 'next' if self._mode == 'array': self._next.hide()
class Game(): def __init__(self, canvas, parent=None, path=None, root=None, mode='array', colors=['#A0FFA0', '#FF8080']): self._canvas = canvas self._parent = parent self._path = path self._root = root self._mode = mode self.current_image = 0 self.playing = False self._timeout_id = None self._prev_mouse_pos = (0, 0) self._start_time = 0 self._colors = ['#FFFFFF'] self._colors.append(colors[0]) self._colors.append(colors[1]) self._canvas.add_events( Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.BUTTON_MOTION_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.POINTER_MOTION_HINT_MASK | Gdk.EventMask.TOUCH_MASK) self._canvas.connect('draw', self.__draw_cb) self._canvas.connect('event', self.__event_cb) self.configure(move=False) self.we_are_sharing = False self._start_time = 0 self._timeout_id = None # Find the image files self._PATHS = glob.glob(os.path.join(self._path, 'images', '*.svg')) # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) a = max(Gdk.Screen.width(), Gdk.Screen.height()) b = min(Gdk.Screen.width(), Gdk.Screen.height()) self._bg_pixbufs = [] if self._parent.tablet_mode: # text on top # landscape self._bg_pixbufs.append(svg_str_to_pixbuf(genhole( a, a, 3 * style.GRID_CELL_SIZE, style.DEFAULT_SPACING, a - 3 * style.GRID_CELL_SIZE, style.GRID_CELL_SIZE * 3 + style.DEFAULT_SPACING))) # portrait self._bg_pixbufs.append(svg_str_to_pixbuf(genhole( a, a, 3 * style.GRID_CELL_SIZE, style.DEFAULT_SPACING, b - 3 * style.GRID_CELL_SIZE, style.GRID_CELL_SIZE * 3 + style.DEFAULT_SPACING))) else: # text on bottom # landscape self._bg_pixbufs.append(svg_str_to_pixbuf(genhole( a, a, 3 * style.GRID_CELL_SIZE, b - style.GRID_CELL_SIZE * 4 - style.DEFAULT_SPACING, a - 3 * style.GRID_CELL_SIZE, b - style.GRID_CELL_SIZE - style.DEFAULT_SPACING))) # portrait self._bg_pixbufs.append(svg_str_to_pixbuf(genhole( a, a, 3 * style.GRID_CELL_SIZE, a - style.GRID_CELL_SIZE * 4 - style.DEFAULT_SPACING, b - 3 * style.GRID_CELL_SIZE, a - style.GRID_CELL_SIZE - style.DEFAULT_SPACING))) if Gdk.Screen.width() > Gdk.Screen.height(): self._bg = Sprite(self._sprites, 0, 0, self._bg_pixbufs[0]) else: self._bg = Sprite(self._sprites, 0, 0, self._bg_pixbufs[1]) self._bg.set_layer(-2) self._bg.type = 'background' size = 3 * self._dot_size + 4 * self._space x = int((Gdk.Screen.width() - size) / 2.) self._dots = [] self._Dots = [] # larger dots for linear mode X = int((Gdk.Screen.width() - self._dot_size * 3) / 2.) Y = style.GRID_CELL_SIZE + self._yoff if self._parent.tablet_mode: yoffset = self._space * 2 + self._yoff else: yoffset = self._yoff for y in range(3): for x in range(3): xoffset = int((self._width - 3 * self._dot_size - 2 * self._space) / 2.) self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space) + yoffset, self._new_dot_surface(color=self._colors[0]))) self._dots[-1].type = -1 # No image self._dots[-1].set_label_attributes(72) self._dots[-1].set_label('?') self._Dots.append( Sprite( self._sprites, X, Y, self._new_dot_surface(color=self._colors[0], large=True))) self._Dots[-1].type = -1 # No image self._Dots[-1].set_label_attributes(72 * 3) self._Dots[-1].set_label('?') self.number_of_images = len(self._PATHS) if USE_ART4APPS: self._art4apps = Art4Apps() self.number_of_images = len(self._art4apps.get_words()) self._record_pixbufs = [] for icon in ['media-audio', 'media-audio-recording']: self._record_pixbufs.append( GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._root, 'icons', icon + '.svg'), style.GRID_CELL_SIZE, style.GRID_CELL_SIZE)) self._play_pixbufs = [] for icon in ['play-inactive', 'play']: self._play_pixbufs.append( GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._root, 'icons', icon + '.svg'), style.GRID_CELL_SIZE, style.GRID_CELL_SIZE)) self._speak_pixbufs = [] for icon in ['speak-inactive', 'speak']: self._speak_pixbufs.append( GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._root, 'icons', icon + '.svg'), style.GRID_CELL_SIZE, style.GRID_CELL_SIZE)) left = style.GRID_CELL_SIZE right = Gdk.Screen.width() - 2 * style.GRID_CELL_SIZE y0 = style.DEFAULT_SPACING + style.DEFAULT_PADDING y1 = y0 + style.GRID_CELL_SIZE y2 = y1 + style.GRID_CELL_SIZE if not self._parent.tablet_mode: dy = Gdk.Screen.height() - 4 * style.GRID_CELL_SIZE - \ 2 * style.DEFAULT_SPACING y0 += dy y1 += dy y2 += dy y3 = int((Gdk.Screen.height() - 2 * style.GRID_CELL_SIZE) / 2) self._record = Sprite( self._sprites, right, y0, self._record_pixbufs[RECORD_OFF]) self._record.set_layer(1) self._record.type = 'record' self._play = Sprite( self._sprites, right, y1, self._play_pixbufs[PLAY_OFF]) self._play.set_layer(1) self._play.type = 'play-inactive' self._speak = Sprite( self._sprites, right, y2, self._speak_pixbufs[SPEAK_OFF]) self._speak.set_layer(1) self._speak.type = 'speak-inactive' self._next_prev_pixbufs = [] for icon in ['go-previous', 'go-next', 'go-previous-inactive', 'go-next-inactive']: self._next_prev_pixbufs.append( GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._root, 'icons', icon + '.svg'), style.GRID_CELL_SIZE, style.GRID_CELL_SIZE)) self._prev = Sprite( self._sprites, left, y3, self._next_prev_pixbufs[PREV_INACTIVE]) self._prev.set_layer(1) self._prev.type = 'prev' if self._mode == 'array': self._prev.hide() self._next = Sprite( self._sprites, right, y3, self._next_prev_pixbufs[NEXT]) self._next.set_layer(1) self._next.type = 'next' if self._mode == 'array': self._next.hide() def configure(self, move=True): self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - style.GRID_CELL_SIZE if not move: if self._height < self._width: self._scale = self._height / (3 * DOT_SIZE * 1.2) else: self._scale = self._width / (3 * DOT_SIZE * 1.2) self._scale /= 1.5 self._dot_size = int(DOT_SIZE * self._scale) if self._parent.tablet_mode: # text on top self._yoff = style.GRID_CELL_SIZE * 3 + style.DEFAULT_SPACING else: self._yoff = style.DEFAULT_SPACING self._space = int(self._dot_size / 5.) return left = style.GRID_CELL_SIZE right = Gdk.Screen.width() - 2 * style.GRID_CELL_SIZE y0 = style.DEFAULT_SPACING + style.DEFAULT_PADDING y1 = y0 + style.GRID_CELL_SIZE y2 = y1 + style.GRID_CELL_SIZE if not self._parent.tablet_mode: dy = Gdk.Screen.height() - 4 * style.GRID_CELL_SIZE - \ 2 * style.DEFAULT_SPACING y0 += dy y1 += dy y2 += dy y3 = int((Gdk.Screen.height() - 2 * style.GRID_CELL_SIZE) / 2) self._record.move((right, y0)) self._play.move((right, y1)) self._speak.move((right, y2)) self._prev.move((left, y3)) self._next.move((right, y3)) # Move the dots X = int((Gdk.Screen.width() - self._dot_size * 3) / 2.) Y = style.GRID_CELL_SIZE + self._yoff if self._parent.tablet_mode: yoffset = self._space * 2 + self._yoff else: yoffset = self._yoff for y in range(3): for x in range(3): xoffset = int((self._width - 3 * self._dot_size - 2 * self._space) / 2.) self._dots[x + y * 3].move( (xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space) + yoffset)) self._Dots[x + y * 3].move((X, Y)) # switch orientation the bg sprite if Gdk.Screen.width() > Gdk.Screen.height(): self._bg.set_image(self._bg_pixbufs[0]) else: self._bg.set_image(self._bg_pixbufs[1]) self._bg.set_layer(-2) def set_speak_icon_state(self, state): if state: self._speak.set_image(self._speak_pixbufs[SPEAK_ON]) self._speak.type = 'speak' else: self._speak.set_image(self._speak_pixbufs[SPEAK_OFF]) self._speak.type = 'speak-inactive' self._speak.set_layer(1) def set_record_icon_state(self, state): if state: self._record.set_image(self._record_pixbufs[RECORD_ON]) else: self._record.set_image(self._record_pixbufs[RECORD_OFF]) self._record.set_layer(1) def set_play_icon_state(self, state): if state: self._play.set_image(self._play_pixbufs[PLAY_ON]) self._play.type = 'play' else: self._play.set_image(self._play_pixbufs[PLAY_OFF]) self._play.type = 'play-inactive' self._play.set_layer(1) def autoplay(self): self.set_mode('linear') # forces current image to 0 self.playing = True self._autonext(next=False) def stop(self): self.playing = False if self._parent.audio_process is not None: self._parent.audio_process.terminate() self._parent.audio_process = None if self._timeout_id is not None: GObject.source_remove(self._timeout_id) self._timeout_id = None self._parent.autoplay_button.set_icon_name('media-playback-start') self._parent.autoplay_button.set_tooltip(_('Play')) self._parent.array_button.set_sensitive(True) def _autonext(self, next=True): self._timeout_id = None if not self.playing: return if next: self._Dots[self.current_image].hide() self.current_image += 1 self._Dots[self.current_image].set_layer(100) if self.current_image == 8: self._next.set_image( self._next_prev_pixbufs[NEXT_INACTIVE]) self._next.set_layer(1) self._prev.set_image(self._next_prev_pixbufs[PREV]) self._prev.set_layer(1) self._parent.check_audio_status() self._parent.check_text_status() GObject.idle_add(self._play_sound) def _poll_audio(self): if self._parent.audio_process is None: # Already stopped? return if self._parent.audio_process.poll() is None: GObject.timeout_add(200, self._poll_audio) else: self._parent.audio_process = None self._next_image() def _play_sound(self): self._start_time = time.time() # Either play back a recording or speak the text if self._play.type == 'play': self._parent.playback_recording_cb() self._poll_audio() elif self._speak.type == 'speak': bounds = self._parent.text_buffer.get_bounds() text = self._parent.text_buffer.get_text( bounds[0], bounds[1], True) speak(text) self._next_image() def _next_image(self): accumulated_time = int(time.time() - self._start_time) if accumulated_time < 5: pause = 5 - accumulated_time else: pause = 1 if self.playing and self.current_image < 8: self._timeout_id = GObject.timeout_add(pause * 1000, self._autonext) else: self.stop() def __event_cb(self, win, event): ''' The mouse button was pressed. Is it on a sprite? or there was a gesture. ''' left = right = False if event.type in (Gdk.EventType.TOUCH_BEGIN, Gdk.EventType.TOUCH_CANCEL, Gdk.EventType.TOUCH_END, Gdk.EventType.BUTTON_PRESS, Gdk.EventType.BUTTON_RELEASE): x = int(event.get_coords()[1]) y = int(event.get_coords()[2]) if event.type in (Gdk.EventType.TOUCH_BEGIN, Gdk.EventType.BUTTON_PRESS): self._prev_mouse_pos = (x, y) elif event.type in (Gdk.EventType.TOUCH_END, Gdk.EventType.BUTTON_RELEASE): if self._parent.audio_process is not None: self._parent.audio_process.terminate() self._parent.audio_process = None terminated_audio = True else: terminated_audio = False if self.playing: self.stop() new_mouse_pos = (x, y) mouse_movement = (new_mouse_pos[0] - self._prev_mouse_pos[0], new_mouse_pos[1] - self._prev_mouse_pos[1]) # horizontal gestures only if (abs(mouse_movement[0]) / 5) > abs(mouse_movement[1]): if abs(mouse_movement[0]) > abs(mouse_movement[1]): if mouse_movement[0] < 0: right = True else: left = True if event.type in (Gdk.EventType.TOUCH_END, Gdk.EventType.BUTTON_RELEASE): spr = self._sprites.find_sprite((x, y)) if left or right or spr is not None: if spr.type in ['record', 'play', 'play-inactive', 'speak', 'speak-inactive']: if spr.type == 'record': self._parent.record_cb() elif spr.type == 'play' and not terminated_audio: self._parent.playback_recording_cb() elif spr.type == 'speak': bounds = self._parent.text_buffer.get_bounds() text = self._parent.text_buffer.get_text( bounds[0], bounds[1], True) speak(text) return elif self._mode == 'array': return self._parent.speak_text_cb() if self._parent.recording: self._parent.record_cb() if (left or spr.type == 'prev') and self.current_image > 0: self._Dots[self.current_image].hide() self.current_image -= 1 self._Dots[self.current_image].set_layer(100) if self.current_image == 0: self._prev.set_image( self._next_prev_pixbufs[PREV_INACTIVE]) self._next.set_image(self._next_prev_pixbufs[NEXT]) elif (right or spr.type == 'next') and self.current_image < 8: self._Dots[self.current_image].hide() self.current_image += 1 self._Dots[self.current_image].set_layer(100) if self.current_image == 8: self._next.set_image( self._next_prev_pixbufs[NEXT_INACTIVE]) self._prev.set_image(self._next_prev_pixbufs[PREV]) elif spr.type not in ['prev', 'background'] and \ self.current_image < 8: self._Dots[self.current_image].hide() self.current_image += 1 self._Dots[self.current_image].set_layer(100) if self.current_image == 8: self._next.set_image( self._next_prev_pixbufs[NEXT_INACTIVE]) self._prev.set_image(self._next_prev_pixbufs[PREV]) self._parent.check_audio_status() self._parent.check_text_status() self._prev.set_layer(1) self._next.set_layer(1) return False def get_mode(self): return self._mode def set_mode(self, mode): self.current_image = 0 self._prev.set_image(self._next_prev_pixbufs[PREV_INACTIVE]) self._next.set_image(self._next_prev_pixbufs[NEXT]) if mode == 'array': self._mode = 'array' self._prev.hide() self._next.hide() else: self._mode = 'linear' self._prev.set_layer(1) self._next.set_layer(1) for i in range(9): if self._mode == 'array': self._dots[i].set_layer(100) self._Dots[i].hide() else: self._dots[i].hide() if self.current_image == i: self._Dots[i].set_layer(100) else: self._Dots[i].hide() def _all_clear(self): ''' Things to reinitialize when starting up a new game. ''' if self._timeout_id is not None: GObject.source_remove(self._timeout_id) self.set_mode(self._mode) if self._mode == 'array': for dot in self._dots: if dot.type != -1: dot.type = -1 dot.set_shape(self._new_dot_surface( self._colors[abs(dot.type)])) dot.set_label('?') else: for dot in self._Dots: if dot.type != -1: dot.type = -1 dot.set_shape(self._new_dot_surface( self._colors[abs(dot.type)], large=True)) dot.set_label('?') self._dance_counter = 0 self._dance_step() def _dance_step(self): ''' Short animation before loading new game ''' if self._mode == 'array': for dot in self._dots: dot.set_shape(self._new_dot_surface( self._colors[int(uniform(0, 3))])) else: self._Dots[0].set_shape(self._new_dot_surface( self._colors[int(uniform(0, 3))], large=True)) self._dance_counter += 1 if self._dance_counter < 10: self._timeout_id = GObject.timeout_add(500, self._dance_step) else: self._new_images() def new_game(self): ''' Start a new game. ''' self._all_clear() def _new_images(self): ''' Select pictures at random ''' used_images = [0] * self.number_of_images for i in range(9): random_selection = int(uniform(0, self.number_of_images)) while used_images[random_selection] != 0: random_selection = int(uniform(0, self.number_of_images)) used_images[random_selection] = 1 self._dots[i].set_label('') self._dots[i].type = random_selection self._dots[i].set_shape(self._new_dot_surface( image=self._dots[i].type)) self._Dots[i].set_label('') self._Dots[i].type = self._dots[i].type self._Dots[i].set_shape(self._new_dot_surface( image=self._Dots[i].type, large=True)) if self._mode == 'array': self._dots[i].set_layer(100) self._Dots[i].hide() else: if self.current_image == i: self._Dots[i].set_layer(100) else: self._Dots[i].hide() self._dots[i].hide() if self.we_are_sharing: self._parent.send_new_images() def restore_game(self, dot_list): ''' Restore a game from the Journal or share ''' self.set_mode(self._mode) for i, dot in enumerate(dot_list): self._dots[i].type = dot self._dots[i].set_shape(self._new_dot_surface( image=self._dots[i].type)) self._dots[i].set_label('') self._Dots[i].type = dot self._Dots[i].set_shape(self._new_dot_surface( image=self._Dots[i].type, large=True)) self._Dots[i].set_label('') if self._mode == 'array': self._dots[i].set_layer(100) self._Dots[i].hide() else: if self.current_image == i: self._Dots[i].set_layer(100) else: self._Dots[i].hide() self._dots[i].hide() def save_game(self): ''' Return dot list for saving to Journal or sharing ''' dot_list = [] for dot in self._dots: dot_list.append(dot.type) return dot_list def set_sharing(self, share=True): self.we_are_sharing = share def _grid_to_dot(self, pos): ''' calculate the dot index from a column and row in the grid ''' return pos[0] + pos[1] * 3 def _dot_to_grid(self, dot): ''' calculate the grid column and row for a dot ''' return [dot % 3, int(dot / 3)] def __draw_cb(self, canvas, cr): self._sprites.redraw_sprites(cr=cr) def __expose_cb(self, win, event): ''' Callback to handle window expose events ''' self.do_expose_event(event) return True # Handle the expose-event by drawing def do_expose_event(self, event): # Create the cairo context cr = self._canvas.window.cairo_create() # Restrict Cairo to the exposed area; avoid extra work cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list if cr is not None: self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit() def export(self): ''' Write dot to cairo surface. ''' if self._mode == 'array': w = h = int(4 * self._space + 3 * self._dot_size) png_surface = cairo.ImageSurface(cairo.FORMAT_RGB24, w, h) cr = cairo.Context(png_surface) cr.set_source_rgb(192, 192, 192) cr.rectangle(0, 0, w, h) cr.fill() for i in range(9): y = self._space + int(i / 3.) * (self._dot_size + self._space) x = self._space + (i % 3) * (self._dot_size + self._space) cr.save() cr.set_source_surface(self._dots[i].images[0], x, y) cr.rectangle(x, y, self._dot_size, self._dot_size) cr.fill() cr.restore() else: w = h = int(2 * self._space + 3 * self._dot_size) png_surface = cairo.ImageSurface(cairo.FORMAT_RGB24, w, h) cr = cairo.Context(png_surface) cr.set_source_rgb(192, 192, 192) cr.rectangle(0, 0, w, h) cr.fill() y = self._space x = self._space cr.save() cr.set_source_surface(self._Dots[self.current_image].images[0], x, y) cr.rectangle(x, y, 3 * self._dot_size, 3 * self._dot_size) cr.fill() cr.restore() return png_surface def _new_dot_surface(self, color='#000000', image=None, large=False): ''' generate a dot of a color color ''' if large: size = self._dot_size * 3 else: size = self._dot_size self._svg_width = size self._svg_height = size if image is None: # color dot self._stroke = color self._fill = color pixbuf = svg_str_to_pixbuf( self._header() + self._circle(size / 2., size / 2., size / 2.) + self._footer()) else: if USE_ART4APPS: word = self._art4apps.get_words()[image] try: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( self._art4apps.get_image_filename(word), size, size) except Exception, e: _logger.error('new dot surface %s %s: %s' % (image, word, e)) word = 'zebra' # default in case image is not found pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( self._art4apps.get_image_filename(word), size, size) else:
def __init__(self, canvas, parent=None, path=None, colors=["#A0FFA0", "#FF8080"]): self._canvas = canvas self._parent = parent self._parent.show_all() self._path = path self._colors = ["#FFFFFF"] self._colors.append(colors[0]) self._colors.append(colors[1]) self._canvas.set_can_focus(True) self._canvas.connect("expose-event", self._expose_cb) self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._height / (4 * DOT_SIZE * 1.3) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.0) self.we_are_sharing = False self._start_time = 0 self._timeout_id = None self._level = 3 self._game = 0 self._correct = 0 # Find the image files self._PATHS = glob.glob(os.path.join(self._path, "images", "*.png")) self._CPATHS = glob.glob(os.path.join(self._path, "color-images", "*.svg")) # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] self._opts = [] yoffset = int(self._space / 2.0) self._line = Sprite( self._sprites, 0, int(3 * (self._dot_size + self._space) + yoffset / 2.0), self._line(vertical=False) ) for y in range(3): for x in range(6): xoffset = int((self._width - 6 * self._dot_size - 5 * self._space) / 2.0) self._dots.append( Sprite( self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space) + yoffset, self._new_dot_surface(color=self._colors[0]), ) ) self._dots[-1].type = -1 # No image self._dots[-1].set_label_attributes(72) y = 3 for x in range(3): self._opts.append( Sprite( self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space) + yoffset, self._new_dot_surface(color=self._colors[0]), ) ) self._opts[-1].type = -1 # No image self._opts[-1].set_label_attributes(72) self._opts[-1].hide()
class Game(): """ The game play -- called from within Sugar or GNOME """ def __init__(self, canvas, path, parent=None): """ Initialize the playing surface """ self.path = path self.activity = parent # starting from command line # we have to do all the work that was done in CardSortActivity.py if parent is None: self.sugar = False self.canvas = canvas # starting from Sugar else: self.sugar = True self.canvas = canvas parent.show_all() self.canvas.set_flags(gtk.CAN_FOCUS) self.canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK) self.canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK) self.canvas.connect("expose-event", self._expose_cb) self.canvas.connect("button-press-event", self._button_press_cb) self.canvas.connect("button-release-event", self._button_release_cb) self.canvas.connect("key_press_event", self._keypress_cb) self.width = gtk.gdk.screen_width() self.height = gtk.gdk.screen_height() - GRID_CELL_SIZE self.card_dim = CARD_DIM self.scale = 0.6 * self.height / (self.card_dim * 3) # Initialize the sprite repository self.sprites = Sprites(self.canvas) # Initialize the grid self.mode = 'rectangle' self.grid = Grid(self, self.mode) self.bounds = LEVEL_BOUNDS[0] self.level = 0 # Start solving the puzzle self.press = None self.release = None self.start_drag = [0, 0] def _button_press_cb(self, win, event): win.grab_focus() x, y = map(int, event.get_coords()) self.start_drag = [x, y] spr = self.sprites.find_sprite((x, y)) if spr is None: self.press = None self.release = None return True # take note of card under button press self.press = spr return True def _button_release_cb(self, win, event): win.grab_focus() x, y = map(int, event.get_coords()) spr = self.sprites.find_sprite((x, y)) if spr is None: self.press = None self.release = None return True # take note of card under button release self.release = spr # if press and release are the same card (click), then rotate if self.press == self.release: self.press.set_layer(0) self.grid.card_table[self.grid.grid[self.grid.spr_to_i( self.press)]].rotate_ccw() if self.mode == 'hexagon': # Rotate a second time self.grid.card_table[self.grid.grid[self.grid.spr_to_i( self.press)]].rotate_ccw() self.press.set_layer(100) else: self.grid.swap(self.press, self.release, self.mode) self.press = None self.release = None if self.test() == True: if self.level < 2: gobject.timeout_add(3000, self.activity.change_play_level_cb, None) return True def _keypress_cb(self, area, event): """ Keypress is used to ... """ k = gtk.gdk.keyval_name(event.keyval) def _expose_cb(self, win, event): ''' Callback to handle window expose events ''' self.do_expose_event(event) return True def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self.canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self.sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): gtk.main_quit() def mask(self, level): """ mask out cards not on play level """ self.grid.hide_list(MASKS[level]) self.bounds = LEVEL_BOUNDS[level] self.level = level def test(self): """ Test the grid to see if the level is solved """ if self.mode != 'rectangle': return False for i in range(24): if i not in MASKS[self.level]: if not self.test_card(i): return False return True def test_card(self, i): """ Test a card with its neighbors; tests are bounded by the level """ row = int(i/6) col = i%6 if row > self.bounds[0][0] and row <= self.bounds[0][1]: if C[self.grid.grid[i]][rotate_index(0, self.grid.card_table[self.grid.grid[i]].orientation)] != \ C[self.grid.grid[i - 6]][rotate_index(1, self.grid.card_table[self.grid.grid[i - 6]].orientation)]: return False if C[self.grid.grid[i]][rotate_index(3, self.grid.card_table[self.grid.grid[i]].orientation)] != \ C[self.grid.grid[i - 6]][rotate_index(2, self.grid.card_table[self.grid.grid[i - 6]].orientation)]: return False if col > self.bounds[2][0] and col <= self.bounds[2][1]: if C[self.grid.grid[i]][rotate_index(3, self.grid.card_table[self.grid.grid[i]].orientation)] != \ C[self.grid.grid[i - 1]][rotate_index(0, self.grid.card_table[self.grid.grid[i - 1]].orientation)]: return False if C[self.grid.grid[i]][rotate_index(2, self.grid.card_table[self.grid.grid[i]].orientation)] != \ C[self.grid.grid[i - 1]][rotate_index(1, self.grid.card_table[self.grid.grid[i - 1]].orientation)]: return False return True
class Game(): def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = [colors[0]] self._colors.append(colors[1]) self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.connect("draw", self.__draw_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._width / (10 * DOT_SIZE * 1.2) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self.max_levels = len(LEVELS_TRUE) self.this_pattern = False # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] self._generate_grid() def _generate_grid(self): ''' Make a new set of dots for a grid of size edge ''' i = 0 for y in range(GRID): for x in range(GRID): xoffset = int((self._width - GRID * self._dot_size - (GRID - 1) * self._space) / 2.) if i < len(self._dots): self._dots[i].move( (xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space) + self._space)) else: self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space) + self._space, self._new_dot(self._colors[0]))) self._dots[i].type = 0 self._dots[-1].set_label_attributes(40) i += 1 def show(self, dot_list): for i in range(GRID * GRID): self._dots[i].set_shape(self._new_dot(self._colors[dot_list[i]])) self._dots[i].type = dot_list[i] def show_true(self): self.show(self._generate_pattern(LEVELS_TRUE[self._activity.level])) self.this_pattern = True def show_false(self): self.show(self._generate_pattern(LEVELS_FALSE[self._activity.level])) self.this_pattern = False def show_random(self): ''' Fill the grid with a true or false pattern ''' if int(uniform(0, 2)) == 0: self.show_true() else: self.show_false() def _initiating(self): return self._activity.initiating def new_game(self): ''' Start a new game. ''' self.show_random() def restore_grid(self, dot_list, boolean): ''' Restore a grid from the share ''' self.show(dot_list) self.this_pattern = boolean def save_grid(self): ''' Return dot list for sharing ''' dot_list = [] for dot in self._dots: dot_list.append(dot.type) return(dot_list, self.this_pattern) def _grid_to_dot(self, pos): ''' calculate the dot index from a column and row in the grid ''' return pos[0] + pos[1] * GRID def _dot_to_grid(self, dot): ''' calculate the grid column and row for a dot ''' return [dot % GRID, int(dot / GRID)] def _set_label(self, string): ''' Set the label in the toolbar or the window frame. ''' self._activity.status.set_label(string) def _generate_pattern(self, f): ''' Run Python code passed as argument ''' userdefined = {} try: exec f in globals(), userdefined return userdefined['generate_pattern'](self) except ZeroDivisionError as e: self._set_label('Python zero-divide error: %s' % (str(e))) except ValueError as e: self._set_label('Python value error: %s' % (str(e))) except SyntaxError as e: self._set_label('Python syntax error: %s' % (str(e))) except NameError as e: self._set_label('Python name error: %s' % (str(e))) except OverflowError as e: self._set_label('Python overflow error: %s' % (str(e))) except TypeError as e: self._set_label('Python type error: %s' % (str(e))) except BaseException: self._set_label('Python error') traceback.print_exc() return None def __draw_cb(self, canvas, cr): self._sprites.redraw_sprites(cr=cr) def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self._canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit() def _new_dot(self, color): ''' generate a dot of a color color ''' self._dot_cache = {} if color not in self._dot_cache: self._stroke = color self._fill = color self._svg_width = self._dot_size self._svg_height = self._dot_size pixbuf = svg_str_to_pixbuf( self._header() + self._circle(self._dot_size / 2., self._dot_size / 2., self._dot_size / 2.) + self._footer()) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self._svg_width, self._svg_height) context = cairo.Context(surface) Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0) context.rectangle(0, 0, self._svg_width, self._svg_height) context.fill() self._dot_cache[color] = surface return self._dot_cache[color] def _header(self): return '<svg\n' + 'xmlns:svg="http://www.w3.org/2000/svg"\n' + \ 'xmlns="http://www.w3.org/2000/svg"\n' + \ 'xmlns:xlink="http://www.w3.org/1999/xlink"\n' + \ 'version="1.1"\n' + 'width="' + str(self._svg_width) + '"\n' + \ 'height="' + str(self._svg_height) + '">\n' def _circle(self, r, cx, cy): return '<circle style="fill:' + str(self._fill) + ';stroke:' + \ str(self._stroke) + ';" r="' + str(r - 0.5) + '" cx="' + \ str(cx) + '" cy="' + str(cy) + '" />\n' def _footer(self): return '</svg>\n'
class Game(): """ The game play -- called from within Sugar or GNOME """ def __init__(self, canvas, path, parent=None): """ Initialize the playing surface """ self.path = path self.activity = parent # starting from command line # we have to do all the work that was done in CardSortActivity.py if parent is None: self.sugar = False self.canvas = canvas # starting from Sugar else: self.sugar = True self.canvas = canvas parent.show_all() self.canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self.canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK) self.canvas.connect("draw", self._draw_cb) self.canvas.connect("button-press-event", self._button_press_cb) self.canvas.connect("button-release-event", self._button_release_cb) self.canvas.connect("key_press_event", self._keypress_cb) self.width = Gdk.Screen.width() self.height = Gdk.Screen.height() - GRID_CELL_SIZE self.card_dim = CARD_DIM self.scale = 0.6 * self.height / (self.card_dim * 3) # Initialize the sprite repository self.sprites = Sprites(self.canvas) # Initialize the grid self.mode = 'rectangle' self.grid = Grid(self, self.mode) self.bounds = LEVEL_BOUNDS[0] self.level = 0 # Start solving the puzzle self.press = None self.release = None self.start_drag = [0, 0] def _button_press_cb(self, win, event): win.grab_focus() x, y = list(map(int, event.get_coords())) self.start_drag = [x, y] spr = self.sprites.find_sprite((x, y)) if spr is None: self.press = None self.release = None return True # take note of card under button press self.press = spr return True def _button_release_cb(self, win, event): win.grab_focus() x, y = list(map(int, event.get_coords())) spr = self.sprites.find_sprite((x, y)) if spr is None: self.press = None self.release = None return True # take note of card under button release self.release = spr # if press and release are the same card (click), then rotate if self.press == self.release: self.press.set_layer(0) self.grid.card_table[self.grid.grid[self.grid.spr_to_i( self.press)]].rotate_ccw() if self.mode == 'hexagon': # Rotate a second time self.grid.card_table[self.grid.grid[self.grid.spr_to_i( self.press)]].rotate_ccw() self.press.set_layer(100) else: self.grid.swap(self.press, self.release, self.mode) self.press = None self.release = None if self.test() == True: if self.level < 2: GLib.timeout_add(3000, self.activity.change_play_level_cb, None) return True def _keypress_cb(self, area, event): """ Keypress is used to ... """ k = Gdk.keyval_name(event.keyval) def _expose_cb(self, win, event): ''' Callback to handle window expose events ''' self.do_expose_event(event) return True def _draw_cb(self, canvas, cr): self.sprites.redraw_sprites(cr=cr) def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self.canvas.props.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self.sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit() def mask(self, level): """ mask out cards not on play level """ self.grid.hide_list(MASKS[level]) self.bounds = LEVEL_BOUNDS[level] self.level = level def test(self): """ Test the grid to see if the level is solved """ if self.mode != 'rectangle': return False for i in range(24): if i not in MASKS[self.level]: if not self.test_card(i): return False return True def test_card(self, i): """ Test a card with its neighbors; tests are bounded by the level """ row = int(i / 6) col = i % 6 if row > self.bounds[0][0] and row <= self.bounds[0][1]: if C[self.grid.grid[i]][rotate_index(0, self.grid.card_table[self.grid.grid[i]].orientation)] != \ C[self.grid.grid[i - 6]][rotate_index(1, self.grid.card_table[self.grid.grid[i - 6]].orientation)]: return False if C[self.grid.grid[i]][rotate_index(3, self.grid.card_table[self.grid.grid[i]].orientation)] != \ C[self.grid.grid[i - 6]][rotate_index(2, self.grid.card_table[self.grid.grid[i - 6]].orientation)]: return False if col > self.bounds[2][0] and col <= self.bounds[2][1]: if C[self.grid.grid[i]][rotate_index(3, self.grid.card_table[self.grid.grid[i]].orientation)] != \ C[self.grid.grid[i - 1]][rotate_index(0, self.grid.card_table[self.grid.grid[i - 1]].orientation)]: return False if C[self.grid.grid[i]][rotate_index(2, self.grid.card_table[self.grid.grid[i]].orientation)] != \ C[self.grid.grid[i - 1]][rotate_index(1, self.grid.card_table[self.grid.grid[i - 1]].orientation)]: return False return True
class Game(): def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = [colors[0]] self._colors.append(colors[1]) self._colors.append('#D0D0D0') self._colors.append('#000000') self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._width / (10 * DOT_SIZE * 1.2) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self.we_are_sharing = False self._edge = 4 self._move_list = [] # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] self._generate_grid() def _generate_grid(self): ''' Make a new set of dots for a grid of size edge ''' i = 0 for y in range(self._edge): for x in range(self._edge): xoffset = int((self._width - self._edge * self._dot_size - (self._edge - 1) * self._space) / 2.) if i < len(self._dots): self._dots[i].move( (xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space))) else: self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space), self._new_dot(self._colors[0]))) self._dots[i].type = 0 self._dots[-1].set_label_attributes(40) i += 1 # and initialize a few variables we'll need. self._all_clear() def _all_clear(self): ''' Things to reinitialize when starting up a new game. ''' self._move_list = [] # Clear dots for dot in self._dots: dot.type = 0 dot.set_shape(self._new_dot(self._colors[0])) dot.set_label('') def _initiating(self): return self._activity.initiating def more_dots(self): ''' Enlarge the grid ''' if self._edge < MAX: self._edge += 1 self._generate_grid() self.new_game() def new_game(self): ''' Start a new game. ''' self._all_clear() # Fill in a few dots to start for i in range(MAX * 2): self._flip_them(int(uniform(0, self._edge * self._edge))) if self.we_are_sharing: _logger.debug('sending a new game') self._parent.send_new_game() def restore_game(self, dot_list, move_list): ''' Restore a game from the Journal or share ''' edge = int(sqrt(len(dot_list))) if edge > MAX: edge = MAX while self._edge < edge: self.more_dots() for i, dot in enumerate(dot_list): self._dots[i].type = dot self._dots[i].set_shape(self._new_dot( self._colors[self._dots[i].type])) if move_list is not None: self._move_list = move_list[:] def save_game(self): ''' Return dot list, move_list for saving to Journal or sharing ''' dot_list = [] for dot in self._dots: dot_list.append(dot.type) return (dot_list, self._move_list) def _set_label(self, string): ''' Set the label in the toolbar or the window frame. ''' self._activity.status.set_label(string) def _button_press_cb(self, win, event): win.grab_focus() x, y = map(int, event.get_coords()) spr = self._sprites.find_sprite((x, y)) if spr is None: return if spr.type is not None: self._flip_them(self._dots.index(spr)) self._test_game_over() if self.we_are_sharing: _logger.debug('sending a click to the share') self._parent.send_dot_click(self._dots.index(spr)) return True def solve(self): ''' Solve the puzzle by undoing moves ''' if self._move_list == []: return self._flip_them(self._move_list.pop(), append=False) GObject.timeout_add(750, self.solve) def _flip_them(self, dot, append=True): ''' flip the dot and its neighbors ''' if append: self._move_list.append(dot) x, y = self._dot_to_grid(dot) self._flip(self._dots[dot]) if x > 0: self._flip(self._dots[dot - 1]) if y > 0: self._flip(self._dots[dot - self._edge]) if x < self._edge - 1: self._flip(self._dots[dot + 1]) if y < self._edge - 1: self._flip(self._dots[dot + self._edge]) def _flip(self, spr): ''' flip a dot ''' spr.type += 1 spr.type %= 2 spr.set_shape(self._new_dot(self._colors[spr.type])) def remote_button_press(self, dot): ''' Receive a button press from a sharer ''' self._flip_them(dot) self._test_game_over() def set_sharing(self, share=True): _logger.debug('enabling sharing') self.we_are_sharing = share def _smile(self): for dot in self._dots: dot.set_label(':)') def _test_game_over(self): ''' Check to see if game is over: all dots the same color ''' match = self._dots[0].type for y in range(self._edge): for x in range(self._edge): if self._dots[y * self._edge + x].type != match: self._set_label(_('keep trying')) return False self._set_label(_('good work')) self._smile() GObject.timeout_add(2000, self.more_dots) return True def _grid_to_dot(self, pos): ''' calculate the dot index from a column and row in the grid ''' return pos[0] + pos[1] * self._edge def _dot_to_grid(self, dot): ''' calculate the grid column and row for a dot ''' return [dot % self._edge, int(dot / self._edge)] def game_over(self, msg=_('Game over')): ''' Nothing left to do except show the results. ''' self._set_label(msg) def __draw_cb(self, canvas, cr): self._sprites.redraw_sprites(cr=cr) def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self._canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit() def _new_dot(self, color): ''' generate a dot of a color color ''' self._dot_cache = {} if color not in self._dot_cache: self._stroke = color self._fill = color self._svg_width = self._dot_size self._svg_height = self._dot_size pixbuf = svg_str_to_pixbuf( self._header() + self._circle(self._dot_size / 2., self._dot_size / 2., self._dot_size / 2.) + self._footer()) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self._svg_width, self._svg_height) context = cairo.Context(surface) Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0) context.rectangle(0, 0, self._svg_width, self._svg_height) context.fill() self._dot_cache[color] = surface return self._dot_cache[color] def _header(self): return '<svg\n' + 'xmlns:svg="http://www.w3.org/2000/svg"\n' + \ 'xmlns="http://www.w3.org/2000/svg"\n' + \ 'xmlns:xlink="http://www.w3.org/1999/xlink"\n' + \ 'version="1.1"\n' + 'width="' + str(self._svg_width) + '"\n' + \ 'height="' + str(self._svg_height) + '">\n' def _circle(self, r, cx, cy): return '<circle style="fill:' + str(self._fill) + ';stroke:' + \ str(self._stroke) + ';" r="' + str(r - 0.5) + '" cx="' + \ str(cx) + '" cy="' + str(cy) + '" />\n' def _footer(self): return '</svg>\n'
def _setup_workspace(self): ''' Prepare to render the datastore entries. ''' # Use the lighter color for the text background if lighter_color(self.colors) == 0: tmp = self.colors[0] self.colors[0] = self.colors[1] self.colors[1] = tmp self._width = gtk.gdk.screen_width() self._height = gtk.gdk.screen_height() self._scale = gtk.gdk.screen_height() / 900. if not HAVE_TOOLBOX and self._hw[0:2] == 'xo': titlef = 18 descriptionf = 12 else: titlef = 36 descriptionf = 24 self._find_starred() for ds in self.dsobjects: if 'title' in ds.metadata: title = ds.metadata['title'] else: title = None pixbuf = None media_object = False mimetype = None if 'mime_type' in ds.metadata: mimetype = ds.metadata['mime_type'] if mimetype[0:5] == 'image': pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( ds.file_path, MAXX, MAXY) # ds.file_path, 300, 225) media_object = True else: pixbuf = get_pixbuf_from_journal(ds, MAXX, MAXY) # 300, 225) if 'description' in ds.metadata: desc = ds.metadata['description'] else: desc = None self.slides.append(Slide(True, ds.object_id, self.colors, title, pixbuf, desc)) # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._help = Sprite( self._sprites, int((self._width - int(PREVIEWW * self._scale)) / 2), int(PREVIEWY * self._scale), gtk.gdk.pixbuf_new_from_file_at_size( os.path.join(activity.get_bundle_path(), 'help.png'), int(PREVIEWW * self._scale), int(PREVIEWH * self._scale))) self._help.hide() self._genblanks(self.colors) self._title = Sprite(self._sprites, 0, 0, self._title_pixbuf) self._title.set_label_attributes(int(titlef * self._scale), rescale=False) self._preview = Sprite(self._sprites, int((self._width - int(PREVIEWW * self._scale)) / 2), int(PREVIEWY * self._scale), self._preview_pixbuf) self._description = Sprite(self._sprites, int(DESCRIPTIONX * self._scale), int(DESCRIPTIONY * self._scale), self._desc_pixbuf) self._description.set_label_attributes(int(descriptionf * self._scale)) self._my_canvas = Sprite(self._sprites, 0, 0, self._canvas_pixbuf) self._my_canvas.set_layer(BOTTOM) self._clear_screen() self.i = 0 self._show_slide() self._playing = False self._rate = 10
class BBoardActivity(activity.Activity): ''' Make a slideshow from starred Journal entries. ''' def __init__(self, handle): ''' Initialize the toolbars and the work surface ''' super(BBoardActivity, self).__init__(handle) self.datapath = get_path(activity, 'instance') self._hw = get_hardware() self._playback_buttons = {} self._audio_recordings = {} self.colors = profile.get_color().to_string().split(',') self._setup_toolbars() self._setup_canvas() self.slides = [] self._setup_workspace() self._buddies = [profile.get_nick_name()] self._setup_presence_service() self._thumbs = [] self._thumbnail_mode = False self._recording = False self._grecord = None self._alert = None self._dirty = False def _setup_canvas(self): ''' Create a canvas ''' self._canvas = gtk.DrawingArea() self._canvas.set_size_request(int(gtk.gdk.screen_width()), int(gtk.gdk.screen_height())) self._canvas.show() self.set_canvas(self._canvas) self.show_all() self._canvas.set_flags(gtk.CAN_FOCUS) self._canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK) self._canvas.add_events(gtk.gdk.POINTER_MOTION_MASK) self._canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK) self._canvas.add_events(gtk.gdk.KEY_PRESS_MASK) self._canvas.connect("expose-event", self._expose_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._canvas.connect("button-release-event", self._button_release_cb) self._canvas.connect("motion-notify-event", self._mouse_move_cb) def _setup_workspace(self): ''' Prepare to render the datastore entries. ''' # Use the lighter color for the text background if lighter_color(self.colors) == 0: tmp = self.colors[0] self.colors[0] = self.colors[1] self.colors[1] = tmp self._width = gtk.gdk.screen_width() self._height = gtk.gdk.screen_height() self._scale = gtk.gdk.screen_height() / 900. if not HAVE_TOOLBOX and self._hw[0:2] == 'xo': titlef = 18 descriptionf = 12 else: titlef = 36 descriptionf = 24 self._find_starred() for ds in self.dsobjects: if 'title' in ds.metadata: title = ds.metadata['title'] else: title = None pixbuf = None media_object = False mimetype = None if 'mime_type' in ds.metadata: mimetype = ds.metadata['mime_type'] if mimetype[0:5] == 'image': pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( ds.file_path, MAXX, MAXY) # ds.file_path, 300, 225) media_object = True else: pixbuf = get_pixbuf_from_journal(ds, MAXX, MAXY) # 300, 225) if 'description' in ds.metadata: desc = ds.metadata['description'] else: desc = None self.slides.append(Slide(True, ds.object_id, self.colors, title, pixbuf, desc)) # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._help = Sprite( self._sprites, int((self._width - int(PREVIEWW * self._scale)) / 2), int(PREVIEWY * self._scale), gtk.gdk.pixbuf_new_from_file_at_size( os.path.join(activity.get_bundle_path(), 'help.png'), int(PREVIEWW * self._scale), int(PREVIEWH * self._scale))) self._help.hide() self._genblanks(self.colors) self._title = Sprite(self._sprites, 0, 0, self._title_pixbuf) self._title.set_label_attributes(int(titlef * self._scale), rescale=False) self._preview = Sprite(self._sprites, int((self._width - int(PREVIEWW * self._scale)) / 2), int(PREVIEWY * self._scale), self._preview_pixbuf) self._description = Sprite(self._sprites, int(DESCRIPTIONX * self._scale), int(DESCRIPTIONY * self._scale), self._desc_pixbuf) self._description.set_label_attributes(int(descriptionf * self._scale)) self._my_canvas = Sprite(self._sprites, 0, 0, self._canvas_pixbuf) self._my_canvas.set_layer(BOTTOM) self._clear_screen() self.i = 0 self._show_slide() self._playing = False self._rate = 10 def _genblanks(self, colors): ''' Need to cache these ''' self._title_pixbuf = svg_str_to_pixbuf( genblank(self._width, int(TITLEH * self._scale), colors)) self._preview_pixbuf = svg_str_to_pixbuf( genblank(int(PREVIEWW * self._scale), int(PREVIEWH * self._scale), colors)) self._desc_pixbuf = svg_str_to_pixbuf( genblank(int(self._width - (2 * DESCRIPTIONX * self._scale)), int(DESCRIPTIONH * self._scale), colors)) self._canvas_pixbuf = svg_str_to_pixbuf( genblank(self._width, self._height, (colors[0], colors[0]))) def _setup_toolbars(self): ''' Setup the toolbars. ''' self.max_participants = 6 if HAVE_TOOLBOX: toolbox = ToolbarBox() # Activity toolbar activity_button_toolbar = ActivityToolbarButton(self) toolbox.toolbar.insert(activity_button_toolbar, 0) activity_button_toolbar.show() self.set_toolbar_box(toolbox) toolbox.show() self.toolbar = toolbox.toolbar self.record_toolbar = gtk.Toolbar() record_toolbar_button = ToolbarButton( label=_('Record a sound'), page=self.record_toolbar, icon_name='media-audio') self.record_toolbar.show_all() record_toolbar_button.show() toolbox.toolbar.insert(record_toolbar_button, -1) else: # Use pre-0.86 toolbar design primary_toolbar = gtk.Toolbar() toolbox = activity.ActivityToolbox(self) self.set_toolbox(toolbox) toolbox.add_toolbar(_('Page'), primary_toolbar) self.record_toolbar = gtk.Toolbar() toolbox.add_toolbar(_('Record'), self.record_toolbar) toolbox.show() toolbox.set_current_toolbar(1) self.toolbar = primary_toolbar self._prev_button = button_factory( 'go-previous-inactive', self.toolbar, self._prev_cb, tooltip=_('Prev slide'), accelerator='<Ctrl>P') self._next_button = button_factory( 'go-next', self.toolbar, self._next_cb, tooltip=_('Next slide'), accelerator='<Ctrl>N') separator_factory(self.toolbar) slide_button = radio_factory('slide-view', self.toolbar, self._slides_cb, group=None, tooltip=_('Slide view')) radio_factory('thumbs-view', self.toolbar, self._thumbs_cb, tooltip=_('Thumbnail view'), group=slide_button) button_factory('view-fullscreen', self.toolbar, self.do_fullscreen_cb, tooltip=_('Fullscreen'), accelerator='<Alt>Return') separator_factory(self.toolbar) journal_button = button_factory( 'write-journal', self.toolbar, self._do_journal_cb, tooltip=_('Update description')) self._palette = journal_button.get_palette() msg_box = gtk.HBox() sw = gtk.ScrolledWindow() sw.set_size_request(int(gtk.gdk.screen_width() / 2), 2 * style.GRID_CELL_SIZE) sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self._text_view = gtk.TextView() self._text_view.set_left_margin(style.DEFAULT_PADDING) self._text_view.set_right_margin(style.DEFAULT_PADDING) self._text_view.set_wrap_mode(gtk.WRAP_WORD_CHAR) self._text_view.connect('focus-out-event', self._text_view_focus_out_event_cb) sw.add(self._text_view) sw.show() msg_box.pack_start(sw, expand=False) msg_box.show_all() self._palette.set_content(msg_box) label_factory(self.record_toolbar, _('Record a sound') + ':') self._record_button = button_factory( 'media-record', self.record_toolbar, self._record_cb, tooltip=_('Start recording')) separator_factory(self.record_toolbar) # Look to see if we have audio previously recorded obj_id = self._get_audio_obj_id() dsobject = self._search_for_audio_note(obj_id) if dsobject is not None: _logger.debug('Found previously recorded audio') self._add_playback_button(profile.get_nick_name(), self.colors, dsobject.file_path) if HAVE_TOOLBOX: button_factory('system-restart', activity_button_toolbar, self._resend_cb, tooltip=_('Refresh')) separator_factory(activity_button_toolbar) self._save_pdf = button_factory( 'save-as-pdf', activity_button_toolbar, self._save_as_pdf_cb, tooltip=_('Save as PDF')) else: separator_factory(self.toolbar) self._save_pdf = button_factory( 'save-as-pdf', self.toolbar, self._save_as_pdf_cb, tooltip=_('Save as PDF')) if HAVE_TOOLBOX: separator_factory(toolbox.toolbar, True, False) stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' toolbox.toolbar.insert(stop_button, -1) stop_button.show() def _do_journal_cb(self, button): self._dirty = True if self._palette: if not self._palette.is_up(): self._palette.popup(immediate=True, state=self._palette.SECONDARY) else: self._palette.popdown(immediate=True) return def _text_view_focus_out_event_cb(self, widget, event): buffer = self._text_view.get_buffer() start_iter = buffer.get_start_iter() end_iter = buffer.get_end_iter() self.slides[self.i].desc = buffer.get_text(start_iter, end_iter) self._show_slide() def _destroy_cb(self, win, event): ''' Clean up on the way out. ''' gtk.main_quit() def _find_starred(self): ''' Find all the favorites in the Journal. ''' self.dsobjects, nobjects = datastore.find({'keep': '1'}) _logger.debug('found %d starred items', nobjects) def _prev_cb(self, button=None): ''' The previous button has been clicked; goto previous slide. ''' if self.i > 0: self.i -= 1 self._show_slide(direction=-1) def _next_cb(self, button=None): ''' The next button has been clicked; goto next slide. ''' if self.i < len(self.slides) - 1: self.i += 1 self._show_slide() def _save_as_pdf_cb(self, button=None): ''' Export an PDF version of the slideshow to the Journal. ''' _logger.debug('saving to PDF...') if 'description' in self.metadata: tmp_file = save_pdf(self, self._buddies, description=self.metadata['description']) else: tmp_file = save_pdf(self, self._buddies) _logger.debug('copying PDF file to Journal...') dsobject = datastore.create() dsobject.metadata['title'] = profile.get_nick_name() + ' ' + \ _('Bboard') dsobject.metadata['icon-color'] = profile.get_color().to_string() dsobject.metadata['mime_type'] = 'application/pdf' dsobject.set_file_path(tmp_file) dsobject.metadata['activity'] = 'org.laptop.sugar.ReadActivity' datastore.write(dsobject) dsobject.destroy() return def _clear_screen(self): ''' Clear the screen to the darker of the two user colors. ''' self._title.hide() self._preview.hide() self._description.hide() if hasattr(self, '_thumbs'): for thumbnail in self._thumbs: thumbnail[0].hide() self.invalt(0, 0, self._width, self._height) # Reset drag settings self._press = None self._release = None self._dragpos = [0, 0] self._total_drag = [0, 0] self.last_spr_moved = None def _update_colors(self): ''' Match the colors to those of the slide originator. ''' if len(self.slides) == 0: return self._genblanks(self.slides[self.i].colors) self._title.set_image(self._title_pixbuf) self._preview.set_image(self._preview_pixbuf) self._description.set_image(self._desc_pixbuf) self._my_canvas.set_image(self._canvas_pixbuf) def _show_slide(self, direction=1): ''' Display a title, preview image, and decription for slide. ''' self._clear_screen() self._update_colors() if len(self.slides) == 0: self._prev_button.set_icon('go-previous-inactive') self._next_button.set_icon('go-next-inactive') self._description.set_label( _('Do you have any items in your Journal starred?')) self._help.set_layer(TOP) self._description.set_layer(MIDDLE) return if self.i == 0: self._prev_button.set_icon('go-previous-inactive') else: self._prev_button.set_icon('go-previous') if self.i == len(self.slides) - 1: self._next_button.set_icon('go-next-inactive') else: self._next_button.set_icon('go-next') pixbuf = self.slides[self.i].pixbuf if pixbuf is not None: self._preview.set_shape(pixbuf.scale_simple( int(PREVIEWW * self._scale), int(PREVIEWH * self._scale), gtk.gdk.INTERP_NEAREST)) self._preview.set_layer(MIDDLE) else: if self._preview is not None: self._preview.hide() self._title.set_label(self.slides[self.i].title) self._title.set_layer(MIDDLE) if self.slides[self.i].desc is not None: self._description.set_label(self.slides[self.i].desc) self._description.set_layer(MIDDLE) text_buffer = gtk.TextBuffer() text_buffer.set_text(self.slides[self.i].desc) self._text_view.set_buffer(text_buffer) else: self._description.set_label('') self._description.hide() def _add_playback_button(self, nick, colors, audio_file): ''' Add a toolbar button for this audio recording ''' if nick not in self._playback_buttons: self._playback_buttons[nick] = button_factory( 'xo-chat', self.record_toolbar, self._playback_recording_cb, cb_arg=nick, tooltip=_('Audio recording by %s') % (nick)) xocolor = XoColor('%s,%s' % (colors[0], colors[1])) icon = Icon(icon_name='xo-chat', xo_color=xocolor) icon.show() self._playback_buttons[nick].set_icon_widget(icon) self._playback_buttons[nick].show() self._audio_recordings[nick] = audio_file def _slides_cb(self, button=None): if self._thumbnail_mode: self._thumbnail_mode = False self.i = self._current_slide self._show_slide() def _thumbs_cb(self, button=None): ''' Toggle between thumbnail view and slideshow view. ''' if not self._thumbnail_mode: self._current_slide = self.i self._thumbnail_mode = True self._clear_screen() self._prev_button.set_icon('go-previous-inactive') self._next_button.set_icon('go-next-inactive') n = int(ceil(sqrt(len(self.slides)))) if n > 0: w = int(self._width / n) else: w = self._width h = int(w * 0.75) # maintain 4:3 aspect ratio x_off = int((self._width - n * w) / 2) x = x_off y = 0 self._thumbs = [] for i in range(len(self.slides)): self._show_thumb(i, x, y, w, h) x += w if x + w > self._width: x = x_off y += h self.i = 0 # Reset position in slideshow to the beginning return False def _show_thumb(self, i, x, y, w, h): ''' Display a preview image and title as a thumbnail. ''' pixbuf = self.slides[i].pixbuf if pixbuf is not None: pixbuf_thumb = pixbuf.scale_simple( int(w), int(h), gtk.gdk.INTERP_TILES) else: pixbuf_thumb = svg_str_to_pixbuf( genblank(int(w), int(h), self.slides[i].colors)) # Create a Sprite for this thumbnail self._thumbs.append([Sprite(self._sprites, x, y, pixbuf_thumb), x, y, i]) self._thumbs[i][0].set_image( svg_str_to_pixbuf(svg_rectangle(int(w), int(h), self.slides[i].colors)), i=1) self._thumbs[i][0].set_layer(TOP) def _expose_cb(self, win, event): ''' Callback to handle window expose events ''' self.do_expose_event(event) return True # Handle the expose-event by drawing def do_expose_event(self, event): # Create the cairo context cr = self.canvas.window.cairo_create() # Restrict Cairo to the exposed area; avoid extra work cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self._sprites.redraw_sprites(cr=cr) def write_file(self, file_path): ''' Clean up ''' if self._dirty: self._save_descriptions_cb() self._dirty = False if os.path.exists(os.path.join(self.datapath, 'output.ogg')): os.remove(os.path.join(self.datapath, 'output.ogg')) def do_fullscreen_cb(self, button): ''' Hide the Sugar toolbars. ''' self.fullscreen() def invalt(self, x, y, w, h): ''' Mark a region for refresh ''' self._canvas.window.invalidate_rect( gtk.gdk.Rectangle(int(x), int(y), int(w), int(h)), False) def _spr_to_thumb(self, spr): ''' Find which entry in the thumbnails table matches spr. ''' for i, thumb in enumerate(self._thumbs): if spr == thumb[0]: return i return -1 def _spr_is_thumbnail(self, spr): ''' Does spr match an entry in the thumbnails table? ''' if self._spr_to_thumb(spr) == -1: return False else: return True def _button_press_cb(self, win, event): ''' The mouse button was pressed. Is it on a thumbnail sprite? ''' win.grab_focus() x, y = map(int, event.get_coords()) self._dragpos = [x, y] self._total_drag = [0, 0] spr = self._sprites.find_sprite((x, y)) self._press = None self._release = None # Are we clicking on a thumbnail? if not self._spr_is_thumbnail(spr): return False self.last_spr_moved = spr self._press = spr self._press.set_layer(DRAG) return False def _mouse_move_cb(self, win, event): """ Drag a thumbnail with the mouse. """ spr = self._press if spr is None: self._dragpos = [0, 0] return False win.grab_focus() x, y = map(int, event.get_coords()) dx = x - self._dragpos[0] dy = y - self._dragpos[1] spr.move_relative([dx, dy]) # Also move the star self._dragpos = [x, y] self._total_drag[0] += dx self._total_drag[1] += dy return False def _button_release_cb(self, win, event): ''' Button event is used to swap slides or goto next slide. ''' win.grab_focus() self._dragpos = [0, 0] x, y = map(int, event.get_coords()) if self._thumbnail_mode: if self._press is None: return # Drop the dragged thumbnail below the other thumbnails so # that you can find the thumbnail beneath it. self._press.set_layer(UNDRAG) i = self._spr_to_thumb(self._press) spr = self._sprites.find_sprite((x, y)) if self._spr_is_thumbnail(spr): self._release = spr # If we found a thumbnail and it is not the one we # dragged, swap their positions. if not self._press == self._release: j = self._spr_to_thumb(self._release) self._thumbs[i][0] = self._release self._thumbs[j][0] = self._press tmp = self.slides[i] self.slides[i] = self.slides[j] self.slides[j] = tmp self._thumbs[j][0].move((self._thumbs[j][1], self._thumbs[j][2])) self._thumbs[i][0].move((self._thumbs[i][1], self._thumbs[i][2])) self._press.set_layer(TOP) self._press = None self._release = None else: self._next_cb() return False def _unit_combo_cb(self, arg=None): ''' Read value of predefined conversion factors from combo box ''' if hasattr(self, '_unit_combo'): active = self._unit_combo.get_active() if active in UNIT_DICTIONARY: self._rate = UNIT_DICTIONARY[active][1] def _record_cb(self, button=None): ''' Start/stop audio recording ''' if self._grecord is None: _logger.debug('setting up grecord') self._grecord = Grecord(self) if self._recording: # Was recording, so stop (and save?) _logger.debug('recording...True. Preparing to save.') self._grecord.stop_recording_audio() self._recording = False self._record_button.set_icon('media-record') self._record_button.set_tooltip(_('Start recording')) _logger.debug('Autosaving recording') self._notify(title=_('Save recording')) gobject.timeout_add(100, self._wait_for_transcoding_to_finish) else: # Wasn't recording, so start _logger.debug('recording...False. Start recording.') self._grecord.record_audio() self._recording = True self._record_button.set_icon('media-recording') self._record_button.set_tooltip(_('Stop recording')) def _wait_for_transcoding_to_finish(self, button=None): while not self._grecord.transcoding_complete(): time.sleep(1) if self._alert is not None: self.remove_alert(self._alert) self._alert = None self._save_recording() def _playback_recording_cb(self, button=None, nick=profile.get_nick_name()): ''' Play back current recording ''' _logger.debug('Playback current recording from %s...' % (nick)) if nick in self._audio_recordings: play_audio_from_file(self._audio_recordings[nick]) return def _get_audio_obj_id(self): ''' Find unique name for audio object ''' if 'activity_id' in self.metadata: obj_id = self.metadata['activity_id'] else: obj_id = _('Bulletin Board') _logger.debug(obj_id) return obj_id def _save_recording(self): if os.path.exists(os.path.join(self.datapath, 'output.ogg')): _logger.debug('Saving recording to Journal...') obj_id = self._get_audio_obj_id() copyfile(os.path.join(self.datapath, 'output.ogg'), os.path.join(self.datapath, '%s.ogg' % (obj_id))) dsobject = self._search_for_audio_note(obj_id) if dsobject is None: dsobject = datastore.create() if dsobject is not None: _logger.debug(self.dsobjects[self.i].metadata['title']) dsobject.metadata['title'] = _('Audio recording by %s') % \ (self.metadata['title']) dsobject.metadata['icon-color'] = \ profile.get_color().to_string() dsobject.metadata['tags'] = obj_id dsobject.metadata['mime_type'] = 'audio/ogg' dsobject.set_file_path( os.path.join(self.datapath, '%s.ogg' % (obj_id))) datastore.write(dsobject) dsobject.destroy() self._add_playback_button( profile.get_nick_name(), self.colors, os.path.join(self.datapath, '%s.ogg' % (obj_id))) if hasattr(self, 'chattube') and self.chattube is not None: self._share_audio() else: _logger.debug('Nothing to save...') return def _search_for_audio_note(self, obj_id): ''' Look to see if there is already a sound recorded for this dsobject ''' dsobjects, nobjects = datastore.find({'mime_type': ['audio/ogg']}) # Look for tag that matches the target object id for dsobject in dsobjects: if 'tags' in dsobject.metadata and \ obj_id in dsobject.metadata['tags']: _logger.debug('Found audio note') return dsobject return None def _save_descriptions_cb(self, button=None): ''' Find the object in the datastore and write out the changes to the decriptions. ''' for s in self.slides: if not s.owner: continue jobject = datastore.get(s.uid) jobject.metadata['description'] = s.desc datastore.write(jobject, update_mtime=False, reply_handler=self.datastore_write_cb, error_handler=self.datastore_write_error_cb) def datastore_write_cb(self): pass def datastore_write_error_cb(self, error): _logger.error('datastore_write_error_cb: %r' % error) def _notify(self, title='', msg=''): ''' Notify user when saves are completed ''' self._alert = Alert() self._alert.props.title = title self._alert.props.msg = msg self.add_alert(self._alert) self._alert.show() def _resend_cb(self, button=None): ''' Resend slides, but only of sharing ''' if hasattr(self, 'chattube') and self.chattube is not None: self._share_slides() self._share_audio() # Serialize def _dump(self, slide): ''' Dump data for sharing.''' _logger.debug('dumping %s' % (slide.uid)) data = [slide.uid, slide.colors, slide.title, pixbuf_to_base64(activity, slide.pixbuf), slide.desc] return self._data_dumper(data) def _data_dumper(self, data): if _OLD_SUGAR_SYSTEM: return json.write(data) else: io = StringIO() jdump(data, io) return io.getvalue() def _load(self, data): ''' Load game data from the journal. ''' slide = self._data_loader(data) if len(slide) == 5: if not self._slide_search(slide[0]): _logger.debug('loading %s' % (slide[0])) self.slides.append(Slide( False, slide[0], slide[1], slide[2], base64_to_pixbuf(activity, slide[3]), slide[4])) def _slide_search(self, uid): ''' Is this slide in the list already? ''' for slide in self.slides: if slide.uid == uid: _logger.debug('skipping %s' % (slide.uid)) return True return False def _data_loader(self, data): if _OLD_SUGAR_SYSTEM: return json.read(data) else: io = StringIO(data) return jload(io) # Sharing-related methods def _setup_presence_service(self): ''' Setup the Presence Service. ''' self.pservice = presenceservice.get_instance() self.initiating = None # sharing (True) or joining (False) owner = self.pservice.get_owner() self.owner = owner self.buddies = [owner] self._share = '' self.connect('shared', self._shared_cb) self.connect('joined', self._joined_cb) def _shared_cb(self, activity): ''' Either set up initial share...''' if self._shared_activity is None: _logger.error('Failed to share or join activity ... \ _shared_activity is null in _shared_cb()') return self.initiating = True self.waiting = False _logger.debug('I am sharing...') self.conn = self._shared_activity.telepathy_conn self.tubes_chan = self._shared_activity.telepathy_tubes_chan self.text_chan = self._shared_activity.telepathy_text_chan self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( 'NewTube', self._new_tube_cb) _logger.debug('This is my activity: making a tube...') id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( SERVICE, {}) def _joined_cb(self, activity): ''' ...or join an exisiting share. ''' if self._shared_activity is None: _logger.error('Failed to share or join activity ... \ _shared_activity is null in _shared_cb()') return self.initiating = False _logger.debug('I joined a shared activity.') self.conn = self._shared_activity.telepathy_conn self.tubes_chan = self._shared_activity.telepathy_tubes_chan self.text_chan = self._shared_activity.telepathy_text_chan self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal(\ 'NewTube', self._new_tube_cb) _logger.debug('I am joining an activity: waiting for a tube...') self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes( reply_handler=self._list_tubes_reply_cb, error_handler=self._list_tubes_error_cb) self.waiting = True def _list_tubes_reply_cb(self, tubes): ''' Reply to a list request. ''' for tube_info in tubes: self._new_tube_cb(*tube_info) def _list_tubes_error_cb(self, e): ''' Log errors. ''' _logger.error('ListTubes() failed: %s', e) def _new_tube_cb(self, id, initiator, type, service, params, state): ''' Create a new tube. ''' _logger.debug('New tube: ID=%d initator=%d type=%d service=%s ' 'params=%r state=%d', id, initiator, type, service, params, state) if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE): if state == telepathy.TUBE_STATE_LOCAL_PENDING: self.tubes_chan[ \ telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id) tube_conn = TubeConnection(self.conn, self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], id, \ group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]) self.chattube = ChatTube(tube_conn, self.initiating, \ self.event_received_cb) if self.waiting: self._send_event('j:%s' % (profile.get_nick_name())) def event_received_cb(self, text): ''' Data is passed as tuples: cmd:text ''' _logger.debug('<<< %s' % (text[0])) if text[0] == 's': # shared journal objects e, data = text.split(':') self._load(data) elif text[0] == 'j': # Someone new has joined e, buddy = text.split(':') _logger.debug('%s has joined' % (buddy)) if buddy not in self._buddies: self._buddies.append(buddy) if self.initiating: self._send_event('J:%s' % (profile.get_nick_name())) self._share_slides() self._share_audio() elif text[0] == 'J': # Everyone must share e, buddy = text.split(':') self.waiting = False if buddy not in self._buddies: self._buddies.append(buddy) _logger.debug('%s has joined' % (buddy)) self._share_slides() self._share_audio() elif text[0] == 'a': # audio recording e, data = text.split(':') nick, colors, base64 = self._data_loader(data) path = os.path.join(activity.get_activity_root(), 'instance', 'nick.ogg') base64_to_file(activity, base64, path) self._add_playback_button(nick, colors, path) def _share_audio(self): if profile.get_nick_name() in self._audio_recordings: base64 = file_to_base64( activity, self._audio_recordings[profile.get_nick_name()]) gobject.idle_add(self._send_event, 'a:' + str( self._data_dumper([profile.get_nick_name(), self.colors, base64]))) def _share_slides(self): for s in self.slides: if s.owner: # Maybe stagger the timing of the sends? gobject.idle_add(self._send_event, 's:' + str(self._dump(s))) _logger.debug('finished sharing') def _send_event(self, text): ''' Send event through the tube. ''' if hasattr(self, 'chattube') and self.chattube is not None: _logger.debug('>>> %s' % (text[0])) self.chattube.SendText(text)
class Game(): def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = [colors[0]] self._colors.append(colors[1]) self._colors.append('#FFFFFF') self._colors.append('#000000') self._colors.append('#FF0000') self._colors.append('#FF8000') self._colors.append('#FFFF00') self._colors.append('#00FF00') self._colors.append('#00FFFF') self._colors.append('#0000FF') self._colors.append('#FF00FF') self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK) self._canvas.add_events(Gdk.EventMask.POINTER_MOTION_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._canvas.connect("button-release-event", self._button_release_cb) self._canvas.connect("motion-notify-event", self._mouse_move_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - GRID_CELL_SIZE scale = [self._width / (10 * DOT_SIZE * 1.2), self._height / (6 * DOT_SIZE * 1.2)] self._scale = min(scale) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self._orientation = 'horizontal' self.we_are_sharing = False self.playing_with_robot = False self._press = False self.last_spr = None self._timer = None self.roygbiv = False # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] for y in range(SIX): for x in range(TEN): xoffset = int((self._width - TEN * self._dot_size - \ (TEN - 1) * self._space) / 2.) self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space), self._new_dot(self._colors[2]))) self._dots[-1].type = 2 # not set self._dots[-1].set_label_attributes(40) self.vline = Sprite(self._sprites, int(self._width / 2.) - 1, 0, self._line(vertical=True)) n = SIX / 2. self.hline = Sprite( self._sprites, 0, int(self._dot_size * n + self._space * (n - 0.5)) - 1, self._line(vertical=False)) self.hline.hide() # and initialize a few variables we'll need. self._all_clear() def _all_clear(self): ''' Things to reinitialize when starting up a new game. ''' for dot in self._dots: dot.type = 2 dot.set_shape(self._new_dot(self._colors[2])) dot.set_label('') self._set_orientation() def _set_orientation(self): ''' Set bar and message for current orientation ''' if self._orientation == 'horizontal': self.hline.hide() self.vline.set_layer(1000) elif self._orientation == 'vertical': self.hline.set_layer(1000) self.vline.hide() else: self.hline.set_layer(1000) self.vline.set_layer(1000) ''' if self._orientation == 'horizontal': self._set_label( _('Click on the dots to make a horizontal reflection.')) elif self._orientation == 'vertical': self._set_label( _('Click on the dots to make a vertical reflection.')) else: self._set_label( _('Click on the dots to make a bilateral reflection.')) ''' def _initiating(self): return self._activity.initiating def new_game(self, orientation='horizontal'): ''' Start a new game. ''' self._orientation = orientation self._all_clear() # Fill in a few dots to start for i in range(int(TEN * SIX / 2)): n = int(uniform(0, TEN * SIX)) if self.roygbiv: self._dots[n].type = int(uniform(2, len(self._colors))) else: self._dots[n].type = int(uniform(0, 4)) self._dots[n].set_shape(self._new_dot( self._colors[self._dots[n].type])) if self.we_are_sharing: _logger.debug('sending a new game') self._parent.send_new_game() def restore_game(self, dot_list, orientation): ''' Restore a game from the Journal or share ''' for i, dot in enumerate(dot_list): self._dots[i].type = dot self._dots[i].set_shape(self._new_dot( self._colors[self._dots[i].type])) self._orientation = orientation self._set_orientation() def save_game(self): ''' Return dot list and orientation for saving to Journal or sharing ''' dot_list = [] for dot in self._dots: dot_list.append(dot.type) return [dot_list, self._orientation] def _set_label(self, string): ''' Set the label in the toolbar or the window frame. ''' self._activity.status.set_label(string) def _button_press_cb(self, win, event): win.grab_focus() x, y = map(int, event.get_coords()) self._press = True spr = self._sprites.find_sprite((x, y)) if spr == None: return True self.last_spr = spr if spr.type is not None: if not self._timer is None: GObject.source_remove(self._timer) self._increment_dot(spr) return True def _button_release_cb(self, win, event): self._press = False if not self._timer is None: GObject.source_remove(self._timer) def _increment_dot(self, spr): spr.type += 1 if self.roygbiv: if spr.type >= len(self._colors): spr.type = 2 else: spr.type %= 4 spr.set_shape(self._new_dot(self._colors[spr.type])) if self.playing_with_robot: self._robot_play(spr) self._test_game_over() if self.we_are_sharing: _logger.debug('sending a click to the share') self._parent.send_dot_click(self._dots.index(spr), spr.type) self._timer = GObject.timeout_add(1000, self._increment_dot, spr) def _mouse_move_cb(self, win, event): """ Drag a tile with the mouse. """ if not self._press: return x, y = map(int, event.get_coords()) spr = self._sprites.find_sprite((x, y)) if spr == self.last_spr: return True if spr is None: return True if spr.type is not None: self.last_spr = spr if not self._timer is None: GObject.source_remove(self._timer) self._increment_dot(spr) def _robot_play(self, dot): ''' Robot reflects dot clicked. ''' x, y = self._dot_to_grid(self._dots.index(dot)) if self._orientation == 'horizontal': x = TEN - x - 1 i = self._grid_to_dot((x, y)) self._dots[i].type = dot.type self._dots[i].set_shape(self._new_dot(self._colors[dot.type])) if self.we_are_sharing: _logger.debug('sending a robot click to the share') self._parent.send_dot_click(i, dot.type) elif self._orientation == 'vertical': y = SIX - y - 1 i = self._grid_to_dot((x, y)) self._dots[i].type = dot.type self._dots[i].set_shape(self._new_dot(self._colors[dot.type])) if self.we_are_sharing: _logger.debug('sending a robot click to the share') self._parent.send_dot_click(i, dot.type) else: x = TEN - x - 1 i = self._grid_to_dot((x, y)) self._dots[i].type = dot.type self._dots[i].set_shape(self._new_dot(self._colors[dot.type])) if self.we_are_sharing: _logger.debug('sending a robot click to the share') self._parent.send_dot_click(i, dot.type) y = SIX - y - 1 i = self._grid_to_dot((x, y)) self._dots[i].type = dot.type self._dots[i].set_shape(self._new_dot(self._colors[dot.type])) if self.we_are_sharing: _logger.debug('sending a robot click to the share') self._parent.send_dot_click(i, dot.type) x = TEN - x - 1 i = self._grid_to_dot((x, y)) self._dots[i].type = dot.type self._dots[i].set_shape(self._new_dot(self._colors[dot.type])) if self.we_are_sharing: _logger.debug('sending a robot click to the share') self._parent.send_dot_click(i, dot.type) def remote_button_press(self, dot, color): ''' Receive a button press from a sharer ''' self._dots[dot].type = color self._dots[dot].set_shape(self._new_dot(self._colors[color])) def set_sharing(self, share=True): _logger.debug('enabling sharing') self.we_are_sharing = share def _smile(self): for dot in self._dots: dot.set_label(':)') def _test_game_over(self): ''' Check to see if game is over ''' if self._orientation == 'horizontal': for y in range(SIX): for x in range(SIX): if self._dots[y * TEN + x].type != \ self._dots[y * TEN + TEN - x - 1].type: self._set_label(_('keep trying')) return False self._set_label(_('good work')) self._smile() return True if self._orientation == 'vertical': for y in range(int(SIX / 2)): for x in range(TEN): if self._dots[y * TEN + x].type != \ self._dots[(SIX - y - 1) * TEN + x].type: self._set_label(_('keep trying')) return False self._set_label(_('good work')) else: for y in range(SIX): for x in range(SIX): if self._dots[y * TEN + x].type != \ self._dots[y * TEN + TEN - x - 1].type: self._set_label(_('keep trying')) return False for y in range(int(SIX / 2)): for x in range(TEN): if self._dots[y * TEN + x].type != \ self._dots[(SIX - y - 1) * TEN + x].type: self._set_label(_('keep trying')) return False self._set_label(_('good work')) self._smile() return True def __draw_cb(self,canvas,cr): self._sprites.redraw_sprites(cr=cr) def _grid_to_dot(self, pos): ''' calculate the dot index from a column and row in the grid ''' return pos[0] + pos[1] * TEN def _dot_to_grid(self, dot): ''' calculate the grid column and row for a dot ''' return [dot % TEN, int(dot / TEN)] def _expose_cb(self, win, event): self.do_expose_event(event) def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self._canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit() def _new_dot(self, color): ''' generate a dot of a color color ''' self._dot_cache = {} if not color in self._dot_cache: self._stroke = color self._fill = color self._svg_width = self._dot_size self._svg_height = self._dot_size pixbuf = svg_str_to_pixbuf( self._header() + \ self._circle(self._dot_size / 2., self._dot_size / 2., self._dot_size / 2.) + \ self._footer()) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self._svg_width, self._svg_height) context = cairo.Context(surface) Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0) context.rectangle(0, 0, self._svg_width, self._svg_height) context.fill() self._dot_cache[color] = surface return self._dot_cache[color] def _line(self, vertical=True): ''' Generate a center line ''' if vertical: self._svg_width = 3 self._svg_height = self._height return svg_str_to_pixbuf( self._header() + \ self._rect(3, self._height, 0, 0) + \ self._footer()) else: self._svg_width = self._width self._svg_height = 3 return svg_str_to_pixbuf( self._header() + \ self._rect(self._width, 3, 0, 0) + \ self._footer()) def _header(self): return '<svg\n' + 'xmlns:svg="http://www.w3.org/2000/svg"\n' + \ 'xmlns="http://www.w3.org/2000/svg"\n' + \ 'xmlns:xlink="http://www.w3.org/1999/xlink"\n' + \ 'version="1.1"\n' + 'width="' + str(self._svg_width) + '"\n' + \ 'height="' + str(self._svg_height) + '">\n' def _rect(self, w, h, x, y): svg_string = ' <rect\n' svg_string += ' width="%f"\n' % (w) svg_string += ' height="%f"\n' % (h) svg_string += ' rx="%f"\n' % (0) svg_string += ' ry="%f"\n' % (0) svg_string += ' x="%f"\n' % (x) svg_string += ' y="%f"\n' % (y) svg_string += 'style="fill:#000000;stroke:#000000;"/>\n' return svg_string def _circle(self, r, cx, cy): return '<circle style="fill:' + str(self._fill) + ';stroke:' + \ str(self._stroke) + ';" r="' + str(r - 0.5) + '" cx="' + \ str(cx) + '" cy="' + str(cy) + '" />\n' def _footer(self): return '</svg>\n'
def __init__(self, canvas, parent=None, path=None): self._canvas = canvas self._parent = parent self._parent.show_all() self._path = path self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() self._scale = self._width / 1200. self._target = 0 self._tries = 0 self.level = 0 self._picture_cards = [] self._small_picture_cards = [] self.food_cards = [] self._group_cards = [] self._quantity_cards = [] self._balance_cards = [] self._last_twenty = [] self._background = None # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._background = Sprite( self._sprites, 0, 0, GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'background.png'), self._width, self._height)) self._background.set_layer(0) self._background.type = None self._background.hide() self.pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'word-box.png'), int(350 * self._scale), int(100 * self._scale)) for i in range(len(FOOD_DATA) / 4): FOOD.append([ FOOD_DATA[i * 4 + NAME], FOOD_DATA[i * 4 + CALS], FOOD_DATA[i * 4 + GROUP], FOOD_DATA[i * 4 + IMAGE] ]) self.food_cards.append(None) self._picture_cards.append(None) for j in range(6): self._small_picture_cards.append(None) self.allocate_food(0) x = 10 dx, dy = self.food_cards[0].get_dimensions() y = 10 for i in range(len(MYPLATE)): self.word_card_append(self._group_cards, self.pixbuf) self._group_cards[-1].type = i self._group_cards[-1].set_label(MYPLATE[i][0]) self._group_cards[-1].move((x, y)) y += int(dy * 1.25) y = 10 for i in range(len(QUANTITIES)): self.word_card_append(self._quantity_cards, self.pixbuf) self._quantity_cards[-1].type = i self._quantity_cards[-1].set_label(QUANTITIES[i]) self._quantity_cards[-1].move((x, y)) y += int(dy * 1.25) y = 10 for i in range(len(BALANCE)): self.word_card_append(self._balance_cards, self.pixbuf) self._balance_cards[-1].type = i self._balance_cards[-1].set_label(BALANCE[i]) self._balance_cards[-1].move((x, y)) y += int(dy * 1.25) self._smile = Sprite( self._sprites, int(self._width / 4), int(self._height / 4), GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'correct.png'), int(self._width / 2), int(self._height / 2))) self._smile.set_label_attributes(36) self._smile.set_margins(10, 0, 10, 0) self._frown = Sprite( self._sprites, int(self._width / 4), int(self._height / 4), GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'wrong.png'), int(self._width / 2), int(self._height / 2))) self._frown.set_label_attributes(36) self._frown.set_margins(10, 0, 10, 0) self.build_food_groups() self._all_clear()
def new_window(canvas, path, parent=None): sw = swWindow() sw.path = path sw.activity = parent # starting from command line # we have to do all the work that was done in CardSortActivity.py if parent is None: sw.sugar = False sw.canvas = canvas # starting from Sugar else: sw.sugar = True sw.canvas = canvas parent.show_all() sw.canvas.set_flags(gtk.CAN_FOCUS) sw.canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK) sw.canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK) sw.canvas.add_events(gtk.gdk.POINTER_MOTION_MASK) sw.canvas.connect("expose-event", _expose_cb, sw) sw.canvas.connect("button-press-event", _button_press_cb, sw) sw.canvas.connect("button-release-event", _button_release_cb, sw) sw.canvas.connect("motion-notify-event", _mouse_move_cb, sw) sw.width = gtk.gdk.screen_width() sw.height = gtk.gdk.screen_height() - GRID_CELL_SIZE sw.sprites = Sprites(sw.canvas) sw.sound = True sw.scale = 2 sw.level = 1 sw.seq = gen_seq(40) sw.counter = 0 sw.playpushed = False # Open the buttons d = W / 4 # position fudge factor sw.buttons_off = [Sprite(sw,"Aoff",sw.width/2-W/2,H/2-d,W/2,H/2),\ Sprite(sw,"Boff",sw.width/2-W-d,H,W/2,H/2),\ Sprite(sw,"Doff",sw.width/2+d,H,W/2,H/2),\ Sprite(sw,"Coff",sw.width/2-W/2,H+H/2+d,W/2,H/2)] sw.buttons_on = [Sprite(sw,"Aon",sw.width/2-W/2,H/2-d,W/2,H/2),\ Sprite(sw,"Bon",sw.width/2-W-d,H,W/2,H/2),\ Sprite(sw,"Don",sw.width/2+d,H,W/2,H/2),\ Sprite(sw,"Con",sw.width/2-W/2,H+H/2+d,W/2,H/2)] sw.sounds = ['dog', 'sheep', 'cat', 'bird'] sw.sound_files = [] # Save sounds for repeated play for i in sw.sounds: playWave(i) path = sw.activity.get_activity_root() + "/instance/" + i + ".csd" sw.sound_files.append(path) audioWrite(path) _all_off(sw) # Start calculating sw.press = None sw.dragpos = 0 return sw
def new_window(canvas, path, parent=None): sw = swWindow() sw.path = path sw.activity = parent if parent is None: sw.sugar = False sw.canvas = canvas else: sw.sugar = True sw.canvas = canvas parent.show_all() sw.canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) sw.canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK) sw.canvas.add_events(Gdk.EventMask.POINTER_MOTION_MASK) sw.canvas.connect("draw", __draw_cb, sw) sw.canvas.connect("button-press-event", _button_press_cb, sw) sw.canvas.connect("button-release-event", _button_release_cb, sw) sw.canvas.connect("motion-notify-event", _mouse_move_cb, sw) sw.width = Gdk.Screen.width() sw.height = Gdk.Screen.height()-GRID_CELL_SIZE sw.sprites = Sprites(sw.canvas) sw.sound = True sw.scale = 2 sw.level = 1 sw.seq = gen_seq(40) sw.counter = 0 sw.playpushed = False # Open the buttons d = W/4 # position fudge factor # Esto hay que "custonearlo" :) bs = str(random.randint(1,65)) gs = str(random.randint(1,65)) rs = str(random.randint(1,65)) ys = str(random.randint(1,65)) if bs == '58': bs = str(random.randint(1,65)) if gs == '58': gs = str(random.randint(1,65)) if rs == '58': rs = str(random.randint(1,65)) if ys == '58': ys = str(random.randint(1,65)) b = "Blue/"+bs g = "Green/"+gs r = "Red/"+rs y = "Yellow/"+ys bon = "Blue_On/"+bs gon = "Green_On/"+gs ron = "Red_On/"+rs yon = "Yellow_On/"+ys Remem = _("Remember") sw.buttons_off = [Sprite(sw,b,sw.width/2-W/2,H/2-d,W/2,H/2),\ Sprite(sw,g,sw.width/2-W-d,H,W/2,H/2),\ Sprite(sw,r,sw.width/2+d,H,W/2,H/2),\ Sprite(sw,y,sw.width/2-W/2,H+H/2+d,W/2,H/2),\ Sprite(sw,Remem,0,610,600,290)] sw.buttons_on = [Sprite(sw,bon,sw.width/2-W/2,H/2-d,W/2,H/2),\ Sprite(sw,gon,sw.width/2-W-d,H,W/2,H/2),\ Sprite(sw,ron,sw.width/2+d,H,W/2,H/2),\ Sprite(sw,yon,sw.width/2-W/2,H+H/2+d,W/2,H/2)] Lista = [_('Blue'),_('Green'),_('Red'),_('Yellow')] print Lista sw.sounds = Lista sw.sound_files = [] # Save sounds for repeated play for i in sw.sounds: playWave(i) path = sw.activity.get_activity_root() + "/instance/" + i + ".csd" sw.sound_files.append(path) audioWrite(path) _all_off(sw) # Start calculating sw.press = None sw.dragpos = 0 return sw
class Game(): def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self.colors = colors # Starting from command line if parent is None: self._running_sugar = False self._canvas = canvas else: self._running_sugar = True self._canvas = canvas parent.show_all() self._canvas.set_flags(gtk.CAN_FOCUS) self._canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK) self._canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK) self._canvas.add_events(gtk.gdk.POINTER_MOTION_MASK) self._canvas.connect("expose-event", self._expose_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._canvas.connect("button-release-event", self._button_release_cb) self._canvas.connect("motion-notify-event", self._mouse_move_cb) self._canvas.connect("key_press_event", self._keypress_cb) self._width = gtk.gdk.screen_width() self._height = gtk.gdk.screen_height() - (GRID_CELL_SIZE * 1.5) self._scale = self._height / (8.0 * TILE_HEIGHT) self.tile_width = TILE_WIDTH * self._scale self.tile_height = TILE_HEIGHT * self._scale # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self.grid = Grid(self._sprites, self._width, self._height, self.tile_width, self.tile_height, self._scale, colors[0]) self.deck = Deck(self._sprites, self._scale, colors[1]) self.deck.board.move((self.grid.left, self.grid.top)) self.hands = [] self.hands.append(Hand(self.tile_width, self.tile_height)) self._errormsg = [] for i in range(4): self._errormsg.append(error_graphic(self._sprites)) self._highlight = highlight_graphic(self._sprites, self._scale) self._score_card = blank_tile(self._sprites, scale=self._scale * 2, color=colors[1]) self._score_card.set_label_attributes(64) self._score_card.move(((int(self._width / 2) - self.tile_width), int(self._height / 2) - self.tile_height)) # and initialize a few variables we'll need. self.buddies = [] self._my_hand = MY_HAND self.playing_with_robot = False self._all_clear() def _all_clear(self): ''' Things to reinitialize when starting up a new game. ''' self._hide_highlight() self._hide_errormsgs() self.deck.hide() self.deck.clear() self.grid.clear() for hand in self.hands: hand.clear() self.show_connected_tiles() self._press = None self._release = None self._dragpos = [0, 0] self._total_drag = [0, 0] self.last_spr_moved = None self._last_tile_played = None self._last_tile_orientation = 0 self._last_grid_played = None self.whos_turn = MY_HAND self._waiting_for_my_turn = False self._waiting_for_robot = False self.placed_a_tile = False self._there_are_errors = False self.score = 0 self._score_card.set_layer(HIDE) self._score_card.move(((int(self._width / 2) - self.tile_width), int(self._height / 2) - self.tile_height)) self.saw_game_over = False def _initiating(self): if not self._running_sugar: return True return self._activity.initiating def new_game(self, saved_state=None, deck_index=0): ''' Start a new game. ''' self._all_clear() # If we are not sharing or we are the sharer... if not self.we_are_sharing() or self._initiating(): # Let joiners know we are starting a new game... if self.we_are_sharing(): self._activity.send_event('n| ') # The initiator shuffles the deck... self.deck.shuffle() # ...and shares it. if self.we_are_sharing(): self._activity.send_event('d|%s' % (self.deck.serialize())) # Deal a hand to yourself... self.hands[self._my_hand].deal(self.deck) # ...deal a hand to the robot... if self.playing_with_robot: if len(self.hands) < ROBOT_HAND + 1: self.hands.append(Hand(self.tile_width, self.tile_height, remote=True)) self.hands[ROBOT_HAND].deal(self.deck) # ...or deal hands to the joiners. elif len(self.buddies) > 1: for i, buddy in enumerate(self.buddies): if buddy != self._activity.nick: self.hands.append(Hand( self.tile_width, self.tile_height, remote=True)) self.hands[i].deal(self.deck) self._activity.send_event('h|%s' % \ (self.hands[i].serialize(buddy=buddy))) # As initiator, you take the first turn. self.its_my_turn() # If we are joining, we need to wait for a hand. else: self._my_hand = self.buddies.index(self._activity.nick) self.its_their_turn(self.buddies[1]) # Sharer will be buddy 1 def we_are_sharing(self): ''' If we are sharing, there is more than one buddy. ''' if len(self.buddies) > 1: return True def _set_label(self, string): ''' Set the label in the toolbar or the window frame. ''' if self._running_sugar: self._activity.status.set_label(string) self._activity.score.set_label(_('Score: ') + str(self.score)) elif hasattr(self, 'win'): self.win.set_title('%s: %s [%d]' % (_('Paths'), string, self.score)) def its_my_turn(self): # I need to play a piece... self.placed_a_tile = False # and I am no longer waiting for my turn. self._waiting_for_my_turn = False # If I don't have any tiles left, time to redeal. if self.hands[self._my_hand].tiles_in_hand() == 0: self._redeal() if self._running_sugar: self._activity.set_player_on_toolbar(self._activity.nick) self._activity.dialog_button.set_icon('go-next') self._activity.dialog_button.set_tooltip( _('Click after taking your turn.')) self._set_label(_('It is your turn.')) def _redeal(self): # Only the sharer deals tiles. if not self.we_are_sharing(): self.hands[self._my_hand].deal(self.deck) if self.playing_with_robot: self.hands[ROBOT_HAND].deal(self.deck) if self.hands[self._my_hand].tiles_in_hand() == 0: if self._running_sugar: self._activity.dialog_button.set_icon( 'media-playback-stop-insensitive') self._activity.dialog_button.set_tooltip(_('Game over')) self.game_over() elif self._initiating(): if self.deck.empty(): self.game_over() return if self.deck.tiles_remaining() < COL * len(self.buddies): number_of_tiles_to_deal = \ int(self.deck.tiles_remaining() / len(self.buddies)) if number_of_tiles_to_deal == 0: number_of_tiles_to_deal = 1 # Deal last tile in deck. else: number_of_tiles_to_deal = COL for i, nick in enumerate(self.buddies): self.hands[i].deal(self.deck, number_of_tiles_to_deal) # Send the joiners their new hands. if nick != self._activity.nick: self._activity.send_event('h|%s' % \ (self.hands[i].serialize(buddy=nick))) def took_my_turn(self): # Did I complete my turn without any errors? if self._there_are_errors: self._set_label(_('There are errors—it is still your turn.')) return # After the tile is placed, expand regions of playable grid squares. self.show_connected_tiles() # Are there any completed paths? self._test_for_complete_paths(self._last_grid_played) # If so, let everyone know what piece I moved. if self.we_are_sharing(): self._activity.send_event('p|%s' % \ (json_dump([self._last_tile_played, self._last_tile_orientation, self._last_grid_played]))) self._last_tile_orientation = 0 # Reset orientation. # I took my turn, so I am waiting again. self._waiting_for_my_turn = True if self.last_spr_moved is not None: self.last_spr_moved.set_layer(TILES) self.last_spr_moved = None self._hide_highlight() self._set_label(_('You took your turn.')) if self.playing_with_robot: self.its_their_turn(_('robot')) self._waiting_for_robot = True gobject.timeout_add(1000, self._robot_turn) elif not self.we_are_sharing(): if self.deck.empty() and \ self.hands[self._my_hand].tiles_in_hand() == 0: self.game_over() else: self.its_my_turn() elif self._initiating(): self.whos_turn += 1 if self.whos_turn == len(self.buddies): self.whos_turn = 0 else: self.its_their_turn(self.buddies[self.whos_turn]) self._activity.send_event('t|%s' % ( self.buddies[self.whos_turn])) def _robot_turn(self): self._robot_play() self.show_connected_tiles() if not self._waiting_for_robot: self.its_my_turn() def its_their_turn(self, nick): # It is someone else's turn. if self._running_sugar: if not self.playing_with_robot: self._activity.set_player_on_toolbar(nick) self._activity.dialog_button.set_icon('media-playback-stop') self._activity.dialog_button.set_tooltip(_('Wait your turn.')) self._set_label(_('Waiting for') + ' ' + nick) self._waiting_for_my_turn = True # I am still waiting. def _button_press_cb(self, win, event): win.grab_focus() x, y = map(int, event.get_coords()) self._dragpos = [x, y] self._total_drag = [0, 0] spr = self._sprites.find_sprite((x, y)) # If it is not my turn, do nothing. if self._waiting_for_my_turn: self._press = None return self._release = None # Ignore clicks on background except to indicate you took your turn if spr is None or spr in self.grid.blanks or spr == self.deck.board: if self.placed_a_tile and spr is None: self.took_my_turn() self._press = None return True # Are we clicking on a tile in the hand? if self.hands[self._my_hand].spr_to_hand(spr) is not None and \ not self._there_are_errors: self.last_spr_moved = spr clicked_in_hand = True if self.placed_a_tile: self._press = None self.took_my_turn() else: clicked_in_hand = False # We cannot switch to an old tile. if spr == self.last_spr_moved: self._press = spr spr.set_layer(TOP) self._show_highlight() return True def _mouse_move_cb(self, win, event): """ Drag a tile with the mouse. """ spr = self._press if spr is None: self._dragpos = [0, 0] return True win.grab_focus() x, y = map(int, event.get_coords()) dx = x - self._dragpos[0] dy = y - self._dragpos[1] spr.move_relative([dx, dy]) self._move_relative_highlight([dx, dy]) self._dragpos = [x, y] self._total_drag[0] += dx self._total_drag[1] += dy def _button_release_cb(self, win, event): win.grab_focus() self._dragpos = [0, 0] if self._waiting_for_my_turn: return if self._press is None: return x, y = map(int, event.get_coords()) spr = self._sprites.find_sprite((x, y)) self._release = spr grid_pos = self.grid.xy_to_grid(x, y) hand_pos = self.hands[self._my_hand].xy_to_hand(x, y) # Placing tile in grid if grid_pos is not None and self._it_is_a_drag() and \ self.grid.blanks[grid_pos].get_layer() > HIDE: # Moving to an empty grid position if self.grid.grid[grid_pos] is None: tile = self.deck.spr_to_tile(self._press) tile.spr.move(self.grid.grid_to_xy(grid_pos)) # If the tile was previously in the grid, empty its old pos. i = self.grid.spr_to_grid(self._press) if i is not None: self.grid.grid[i] = None # Assign the tile to the new grid position. self.grid.grid[grid_pos] = tile self.placed_a_tile = True self._last_tile_played = tile.number self._last_grid_played = grid_pos # If the tile came from the hand, empty its old position. i = self.hands[self._my_hand].spr_to_hand(self._press) if i is not None: self.hands[self._my_hand].hand[i] = None # Remember which tile moved. if self.last_spr_moved != tile.spr: self.last_spr_moved = tile.spr self._show_highlight() # Returning tile to hand elif hand_pos is not None: # Make sure there is somewhere to place the tile. empty = self.hands[self._my_hand].find_empty_slot() if empty is not None: tile = self.deck.spr_to_tile(self._press) tile.spr.move(self.hands[self._my_hand].hand_to_xy(empty)) # Did the tile come from elsewhere in the hand? if self.hands[self._my_hand].spr_to_hand( self._press) is not None: self.hands[self._my_hand].hand[self.hands[ self._my_hand].spr_to_hand(self._press)] = None # or from the grid? elif self.grid.spr_to_grid(self._press) is not None: self.grid.grid[self.grid.spr_to_grid(self._press)] = None self.hands[self._my_hand].hand[empty] = tile # Remember which tile moved. if spr == self.last_spr_moved: self.last_spr_moved = None self._hide_errormsgs() self._there_are_errors = False else: # Or return tile to the grid grid_pos = self.grid.spr_to_grid(self._press) if grid_pos is not None: tile = self.deck.spr_to_tile(self._press) tile.spr.move(self.grid.grid_to_xy(grid_pos)) self._hide_highlight() self._press = None self._release = None self.placed_a_tile = False return True # Rotate elif self._press == self._release and not self._it_is_a_drag(): tile = self.deck.spr_to_tile(spr) tile.rotate_clockwise() self._last_tile_orientation = tile.orientation # Remember which tile moved. if self.last_spr_moved != tile.spr: self.last_spr_moved = tile.spr self._show_highlight() # In limbo: return to grid if hand_pos is None and x < self.grid.left: grid_pos = self.grid.spr_to_grid(self._press) if grid_pos is not None: tile = self.deck.spr_to_tile(self._press) tile.spr.move(self.grid.grid_to_xy(grid_pos)) self._hide_highlight() self._snap_to_grid(self._release) self._test_for_bad_paths(self.grid.spr_to_grid(self._press)) self._press = None self._release = None return True def _snap_to_grid(self, spr): ''' make sure a tile is aligned in its grid position ''' for i in range(COL * ROW): if self.grid.grid[i] is not None: self.grid.grid[i].spr.move(self.grid.grid_to_xy(i)) if self.grid.grid[i].spr == spr: self._move_highlight(self.grid.grid_to_xy(i)) def _it_is_a_drag(self): ''' The movement was large enough to be consider a drag as opposed to a tile rotate. ''' if self._total_drag[0] * self._total_drag[0] + \ self._total_drag[1] * self._total_drag[1] > \ self.tile_width * self.tile_height: return True return False def _shuffle_up(self, hand): ''' Shuffle all the tiles in a hand to the top. ''' for i, tile in enumerate(self.hands[hand].hand): empty = self.hands[hand].find_empty_slot() if i > 0 and tile is not None and empty is not None: tile.spr.move(self.hands[hand].hand_to_xy(empty)) self.hands[hand].hand[empty] = tile self.hands[hand].hand[i] = None def game_over(self, msg=_('Game over')): ''' Nothing left to do except show the results. ''' self._set_label(msg) self.saw_game_over = True if self.hands[self._my_hand].tiles_in_hand() == 0: self.score += 50 # Bonus points else: for tile in self.hands[self._my_hand].hand: if tile is not None: self.score -= 2 * tile.get_value() # Penalty self._shuffle_up(self._my_hand) if self._running_sugar: self._activity.score.set_label(_('Score: ') + str(self.score)) self._score_card.set_label(str(self.score)) self._score_card.set_layer(OVER_THE_TOP) self._score_card.move((int(self.tile_width / 2), int(self._height / 2) + 2 * self.tile_height)) if self.playing_with_robot: self._shuffle_up(ROBOT_HAND) for tile in range(COL): if self.hands[ROBOT_HAND].hand[tile] is not None: x, y = self.hands[ROBOT_HAND].hand_to_xy(tile) self.hands[ROBOT_HAND].hand[tile].spr.move( (self.grid.left_hand + self.grid.xinc, y)) if self._running_sugar: self._activity.set_robot_status(False, 'robot-off') elif self.we_are_sharing(): self._activity.send_event('g| ') def show_connected_tiles(self): ''' Highlight the squares that surround the tiles already on the grid. ''' for i in range(ROW * COL): if self._connected(i): self.grid.blanks[i].set_layer(GRID) else: self.grid.blanks[i].set_layer(HIDE) def _connected(self, tile): ''' Does tile abut the path? ''' if self.grid.grid.count(None) == ROW * COL: return True if self.grid.grid[tile] is not None: # already has a tile return False # Looking north if tile >= COL and self.grid.grid[tile + OFFSETS[0]] is not None: return True # Looking east if tile % ROW < ROW - 1 and \ self.grid.grid[tile + OFFSETS[1]] is not None: return True # Looking south if tile < (ROW - 1) * COL and \ self.grid.grid[tile + OFFSETS[2]] is not None: return True # Looking west if tile % ROW > 0 and self.grid.grid[tile + OFFSETS[3]] is not None: return True return False def give_a_hint(self): ''' Try to find an open place on the grid for any tile in my_hand. ''' order = self.deck.random_order(ROW * COL) for i in range(ROW * COL): if self._connected(order[i]): for tile in self.hands[self._my_hand].hand: if self._try_placement(tile, order[i]): # Success, so give hint. self.grid.grid[order[i]] = None self._show_highlight( pos=self.grid.grid_to_xy(order[i])) return # Nowhere to play. self.game_over(_('Nowhere to play.')) def _robot_play(self): ''' The robot tries random tiles in random locations. ''' # TODO: strategy try to complete paths order = self.deck.random_order(ROW * COL) for i in range(ROW * COL): if self._connected(order[i]): for tile in self.hands[ROBOT_HAND].hand: if self._try_placement(tile, order[i]): # Success, so remove tile from hand. self.hands[ROBOT_HAND].hand[ self.hands[ROBOT_HAND].hand.index(tile)] = None tile.spr.move(self.grid.grid_to_xy(order[i])) tile.spr.set_layer(TILES) self._waiting_for_robot = False return # If we didn't return above, we were unable to play a tile. self.game_over(_('Robot unable to play')) def _try_placement(self, tile, i): ''' Try to place a tile at grid posiion i. Rotate it, if necessary. ''' if tile is None: return False self.grid.grid[i] = tile for j in range(4): self._test_for_bad_paths(i) if not self._there_are_errors: return True tile.rotate_clockwise() self.grid.grid[i] = None return False def _test_for_complete_paths(self, tile): ''' Did this tile complete a path? (or two paths?) ''' # A tile can complete up to two paths. self._paths = [[], []] break_in_path = [False, False] # Seed the paths and lists with the current tile. if tile is not None: self._add_to_path_list(tile, 0, 0) if len(self.grid.grid[tile].paths) == 2: self._add_to_path_list(tile, 1, 1) # Walk the path. for p in range(2): tile, path = self._tile_to_test(p) while(tile is not None): self._test(tile, path, p, self._test_a_neighbor) self._tile_has_been_tested(tile, path, p) tile, path = self._tile_to_test(p) # Is the path complete? for i in self._paths[p]: if not self._test(i[0], i[1], None, self._test_a_connection): break_in_path[p] = True if not break_in_path[p] and len(self._paths[p]) > 0: for i in self._paths[p]: self.grid.grid[i[0]].set_shape(i[1]) self.score += self.grid.grid[i[0]].get_value() def _tile_to_test(self, test_path): ''' Find a tile that needs testing. ''' for i in self._paths[test_path]: if i[2] is False: return i[0], i[1] return None, None def _add_to_path_list(self, tile, tile_path, test_path): ''' Only add a tile to the path if it is not already there. ''' for i in self._paths[test_path]: if i[0] == tile and i[1] == tile_path: return self._paths[test_path].append([tile, tile_path, False]) def _tile_has_been_tested(self, tile, tile_path, test_path): ''' Mark a tile as tested. ''' for i in self._paths[test_path]: if i[0] == tile and i[1] == tile_path: i[2] = True return def _test(self, tile, tile_path, test_path, test): ''' Test each neighbor of a block for a connecting path. ''' if tile is None: return False for i in range(4): if not test(tile, tile_path, test_path, i, tile + OFFSETS[i]): return False return True def _test_a_connection(self, tile, tile_path, test_path, direction, neighbor): ''' Is there a break in the connection? If so return False. ''' if self.grid.grid[tile].paths[tile_path][direction] == 1: if self.grid.grid[neighbor] is None: return False # Which of the neighbor's paths are we connecting to? if len(self.grid.grid[neighbor].paths) == 1: if self.grid.grid[neighbor].paths[0][(direction + 2) % 4] == 0: return False else: return True if self.grid.grid[neighbor].paths[0][(direction + 2) % 4] == 0 and\ self.grid.grid[neighbor].paths[1][(direction + 2) % 4] == 0: return False return True def _test_a_neighbor(self, tile, tile_path, test_path, direction, neighbor): ''' Are we connected to a neighbor's path? If so, add the neighbor to our paths list and to the list of tiles that need to be tested. ''' if self.grid.grid[tile].paths[tile_path][direction] == 1: if self.grid.grid[neighbor] is not None: if not neighbor in self._paths[test_path]: # Which of the neighbor's paths are we connecting to? if self.grid.grid[neighbor].paths[0][ (direction + 2) % 4] == 1: self._add_to_path_list(neighbor, 0, test_path) elif len(self.grid.grid[neighbor].paths) == 2 and \ self.grid.grid[neighbor].paths[1][ (direction + 2) % 4] == 1: self._add_to_path_list(neighbor, 1, test_path) return True def _test_for_bad_paths(self, tile): ''' Is there a path to nowhere? ''' self._hide_errormsgs() self._there_are_errors = False if tile is not None: self._check_tile(tile, [int(tile / COL), 0], NORTH, tile + OFFSETS[0]) self._check_tile(tile, [tile % ROW, ROW - 1], EAST, tile + OFFSETS[1]) self._check_tile(tile, [int(tile / COL), COL - 1], SOUTH, tile + OFFSETS[2]) self._check_tile(tile, [tile % ROW, 0], WEST, tile + OFFSETS[3]) def _check_tile(self, i, edge_check, direction, neighbor): ''' Can a tile be placed at position i? ''' if edge_check[0] == edge_check[1]: for path in self.grid.grid[i].paths: if path[direction] == 1: self._display_errormsg(i, direction) else: if self.grid.grid[neighbor] is not None: my_path = 0 your_path = 0 for c in self.grid.grid[i].paths: if c[direction] == 1: my_path = 1 for c in self.grid.grid[neighbor].paths: if c[(direction + 2) % 4] == 1: your_path = 1 if my_path != your_path: self._display_errormsg(i, direction) def _display_errormsg(self, i, direction): ''' Display an error message where and when appropriate. ''' if self._press is not None: dxdy = [[0.375, -0.125], [0.875, 0.375], [0.375, 0.875], [-0.125, 0.375]] x, y = self._press.get_xy() self._errormsg[direction].move( (x + dxdy[direction][0] * self.tile_width, y + dxdy[direction][1] * self.tile_height)) self._errormsg[direction].set_layer(OVER_THE_TOP) self._there_are_errors = True def _hide_errormsgs(self): ''' Hide all the error messages. ''' for i in range(4): self._errormsg[i].move((self.grid.left, self.grid.top)) self._errormsg[i].set_layer(HIDE) def _hide_highlight(self): ''' No tile is selected. ''' for i in range(4): self._highlight[i].move((self.grid.left, self.grid.top)) self._highlight[i].set_layer(HIDE) def _move_relative_highlight(self, pos): for i in range(4): self._highlight[i].move_relative(pos) def _move_highlight(self, pos): x, y = pos self._highlight[0].move((x, y)) self._highlight[1].move((x + 7 * self.tile_width / 8, y)) self._highlight[2].move((x + 7 * self.tile_width / 8, y + 7 * self.tile_height / 8)) self._highlight[3].move((x, y + 7 * self.tile_height / 8)) def _show_highlight(self, pos=None): ''' Highlight the tile that is selected. ''' if self.last_spr_moved is None and pos is None: self._hide_highlight() else: if pos is None: x, y = self.last_spr_moved.get_xy() else: # Giving a hint. x, y = pos self._move_highlight((x, y)) for i in range(4): self._highlight[i].set_layer(OVER_THE_TOP) def _keypress_cb(self, area, event): return True def _expose_cb(self, win, event): ''' Callback to handle window expose events ''' self.do_expose_event(event) return True def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self._canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): gtk.main_quit()
class Yupana(): def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = ['#FFFFFF'] self._colors.append(colors[0]) self._colors.append(colors[1]) self._colors.append('#000000') self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._width / (20 * DOT_SIZE * 1.1) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self.we_are_sharing = False self._sum = 0 self._mode = 'ten' self.custom = [1, 1, 1, 1, 10] # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) Sprite(self._sprites, 0, 0, self._box(self._width, self._height, color=colors[1])) self._number_box = Sprite(self._sprites, 0, 0, self._box( self._width, 2 * self._dot_size, color=colors[1])) self._number_box.set_label_attributes(48) self._dots = [] for p in range(SIX): y = self._height - self._space Sprite(self._sprites, 0, y, self._line(vertical=False)) x = int(p * self._width / 6) + self._space y -= self._dot_size for d in range(3): # bottom of fives row self._dots.append( Sprite(self._sprites, x, y, self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set # self._dots[-1].set_label_color('white') x += self._dot_size + self._space x = int((p * self._width / 6.) + self._dot_size / 2.) + self._space y -= self._dot_size + self._space for d in range(2): # top of fives row self._dots.append( Sprite(self._sprites, x, y, self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set # self._dots[-1].set_label_color('white') x += self._dot_size + self._space y -= self._dot_size Sprite(self._sprites, 0, y, self._line(vertical=False)) x = int((p * self._width / 6.) + self._dot_size / 2.) + self._space y -= self._dot_size for d in range(2): # bottom of threes row self._dots.append( Sprite(self._sprites, x, y, self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set # self._dots[-1].set_label_color('white') x += self._dot_size + self._space x = int((p * self._width / 6.) + self._dot_size) + self._space y -= self._dot_size + self._space for d in range(1): # top of threes row self._dots.append( Sprite(self._sprites, x, y, self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set # self._dots[-1].set_label_color('white') x += self._dot_size + self._space y -= self._dot_size Sprite(self._sprites, 0, y, self._line(vertical=False)) x = int((p * self._width / 6.) + self._dot_size / 2.) + self._space y -= self._dot_size for d in range(2): # twos row self._dots.append( Sprite(self._sprites, x, y, self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set # self._dots[-1].set_label_color('white') x += self._dot_size + self._space y -= self._dot_size Sprite(self._sprites, 0, y, self._line(vertical=False)) x = int((p * self._width / 6.) + self._dot_size) + self._space y -= self._dot_size for d in range(1): # ones row self._dots.append( Sprite(self._sprites, x, y, self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set # self._dots[-1].set_label_color('white') x += self._dot_size + self._space y -= self._dot_size Sprite(self._sprites, 0, y, self._line(vertical=False)) for p in range(SIX - 1): x = int((p + 1) * self._width / 6) Sprite(self._sprites, x - 1, y, self._line(vertical=True)) # and initialize a few variables we'll need. self._all_clear() def _all_clear(self): ''' Things to reinitialize when starting up a new yupana. ''' self._sum = 0 for dot in self._dots: if dot.type > 0: dot.type = 0 dot.set_shape(self._new_dot(self._colors[0])) dot.set_label('') self._set_label(str(self._sum)) def _initiating(self): return self._activity.initiating def new_yupana(self, mode=None): ''' Create a new yupana. ''' self._all_clear() if mode is not None: self._mode = mode o = (SIX - 1) * (TEN + 1) # only label units if mode == 'ten': for i in range(TEN + 1): self._dots[o + i].set_label('1') self._dots[o - 1].set_label('10') elif mode == 'twenty': for i in range(TEN + 1): if i in [7, 10]: self._dots[o + i].set_label('1') else: self._dots[o + i].set_label('2') self._dots[o - 1].set_label('20') elif mode == 'factor': for i in range(TEN + 1): if i in [10]: self._dots[o + i].set_label('1') elif i in [8, 9]: self._dots[o + i].set_label('2') elif i in [5, 6, 7]: self._dots[o + i].set_label('3') else: self._dots[o + i].set_label('5') self._dots[o - 1].set_label('10') elif mode == 'fibonacci': for i in range(TEN + 1): if i in [10]: self._dots[o + i].set_label('1') elif i in [8, 9]: self._dots[o + i].set_label('2') elif i in [5, 6, 7]: self._dots[o + i].set_label('5') else: self._dots[o + i].set_label('20') self._dots[o - 1].set_label('60') else: # custom for i in range(TEN + 1): if i in [10]: self._dots[o + i].set_label(str(self.custom[0])) elif i in [8, 9]: self._dots[o + i].set_label(str(self.custom[1])) elif i in [5, 6, 7]: self._dots[o + i].set_label(str(self.custom[2])) else: self._dots[o + i].set_label(str(self.custom[3])) self._dots[o - 1].set_label(str(self.custom[4])) if self.we_are_sharing: _logger.debug('sending a new yupana') self._parent.send_new_yupana() def restore_yupana(self, dot_list): ''' Restore a yumpana from the Journal or share ''' for i, dot in enumerate(dot_list): self._dots[i].type = dot self._dots[i].set_shape(self._new_dot( self._colors[self._dots[i].type])) if self._dots[i].type == 1: self._sum += self._calc_bead_value(i) self._set_label(str(self._sum)) def save_yupana(self): ''' Return dot list and orientation for saving to Journal or sharing ''' dot_list = [] for dot in self._dots: dot_list.append(dot.type) return [self._mode, dot_list] def _set_label(self, string): ''' Set the label in the toolbar or the window frame. ''' self._number_box.set_label(string) # self._activity.status.set_label(string) def _button_press_cb(self, win, event): win.grab_focus() x, y = map(int, event.get_coords()) spr = self._sprites.find_sprite((x, y)) if spr == None: return if spr.type is not None: spr.type += 1 spr.type %= 2 spr.set_shape(self._new_dot(self._colors[spr.type])) if self.we_are_sharing: _logger.debug('sending a click to the share') self._parent.send_dot_click(self._dots.index(spr), spr.type) if spr.type == 1: self._sum += self._calc_bead_value(self._dots.index(spr)) else: self._sum -= self._calc_bead_value(self._dots.index(spr)) self._set_label(str(self._sum)) return True def _calc_bead_value(self, i): ''' Calculate a bead value based on the index and the mode ''' e = 5 - i / (TEN + 1) m = i % 11 if self._mode == 'ten': return 10 ** e elif self._mode == 'twenty': if m in [7, 10]: return 20 ** e else: return (20 ** e) * 2 elif self._mode == 'factor': if m in [10]: return 10 ** e elif m in [8, 9]: return (10 ** e) * 2 elif m in [5, 6, 7]: return (10 ** e) * 3 else: return (10 ** e) * 5 elif self._mode == 'fibonacci': if m in [10]: return 60 ** e elif m in [8, 9]: return (60 ** e) * 2 elif m in [5, 6, 7]: return (60 ** e) * 5 else: return (60 ** e) * 20 else: # custom if m in [10]: return (self.custom[4] ** e) * self.custom[0] elif m in [8, 9]: return (self.custom[4] ** e) * self.custom[1] elif m in [5, 6, 7]: return (self.custom[4] ** e) * self.custom[2] else: return (self.custom[4] ** e) * self.custom[3] def remote_button_press(self, dot, color): ''' Receive a button press from a sharer ''' self._dots[dot].type = color self._dots[dot].set_shape(self._new_dot(self._colors[color])) def set_sharing(self, share=True): _logger.debug('enabling sharing') self.we_are_sharing = share def _grid_to_dot(self, pos): ''' calculate the dot index from a column and row in the grid ''' return pos[0] + pos[1] * TEN def _dot_to_grid(self, dot): ''' calculate the grid column and row for a dot ''' return [dot % TEN, int(dot / TEN)] def __draw_cb(self, canvas, cr): self._sprites.redraw_sprites(cr=cr) def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self._canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit() def _new_dot(self, color): ''' generate a dot of a color color ''' def darken(color): ''' return a darker color than color ''' gdk_fill_color = Gdk.color_parse(self._fill) gdk_fill_dark_color = Gdk.Color( int(gdk_fill_color.red * 0.5), int(gdk_fill_color.green * 0.5), int(gdk_fill_color.blue * 0.5)).to_string() return str(gdk_fill_dark_color) self._dot_cache = {} if not color in self._dot_cache: self._stroke = color self._fill = color self._fill_dark = darken(color) self._svg_width = self._dot_size self._svg_height = self._dot_size if color in ['#FFFFFF', '#000000']: pixbuf = svg_str_to_pixbuf( self._header() + \ self._circle(self._dot_size / 2., self._dot_size / 2., self._dot_size / 2.) + \ self._footer()) else: pixbuf = svg_str_to_pixbuf( self._header() + \ self._def(self._dot_size) + \ self._gradient(self._dot_size / 2., self._dot_size / 2., self._dot_size / 2.) + \ self._footer()) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self._svg_width, self._svg_height) context = cairo.Context(surface) Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0) context.rectangle(0, 0, self._svg_width, self._svg_height) context.fill() self._dot_cache[color] = surface return self._dot_cache[color] def _line(self, vertical=True): ''' Generate a center line ''' if vertical: self._svg_width = 3 self._svg_height = self._dot_size * 10 + self._space * 2 return svg_str_to_pixbuf( self._header() + \ self._rect(3, self._dot_size * 10 + self._space * 2, 0, 0) + \ self._footer()) else: self._svg_width = self._width self._svg_height = 3 return svg_str_to_pixbuf( self._header() + \ self._rect(self._width, 3, 0, 0) + \ self._footer()) def _box(self, w, h, color='white'): ''' Generate a box ''' self._svg_width = w self._svg_height = h return svg_str_to_pixbuf( self._header() + \ self._rect(self._svg_width, self._svg_height, 0, 0, color=color) + \ self._footer()) def _header(self): return '<svg\n' + 'xmlns:svg="http://www.w3.org/2000/svg"\n' + \ 'xmlns="http://www.w3.org/2000/svg"\n' + \ 'xmlns:xlink="http://www.w3.org/1999/xlink"\n' + \ 'version="1.1"\n' + 'width="' + str(self._svg_width) + '"\n' + \ 'height="' + str(self._svg_height) + '">\n' def _rect(self, w, h, x, y, color='black'): svg_string = ' <rect\n' svg_string += ' width="%f"\n' % (w) svg_string += ' height="%f"\n' % (h) svg_string += ' rx="%f"\n' % (0) svg_string += ' ry="%f"\n' % (0) svg_string += ' x="%f"\n' % (x) svg_string += ' y="%f"\n' % (y) if color == 'black': svg_string += 'style="fill:#000000;stroke:#000000;"/>\n' elif color == 'white': svg_string += 'style="fill:#ffffff;stroke:#ffffff;"/>\n' else: svg_string += 'style="fill:%s;stroke:%s;"/>\n' % (color, color) return svg_string def _circle(self, r, cx, cy): scale = (DOT_SIZE * self._scale) / 55. return '\ <g transform="matrix(%f,0,0,%f,0,0)">\ <path\ d="m 35.798426,4.2187227 c -2.210658,0.9528967 -4.993612,-0.9110169 -7.221856,0 C 23.805784,6.1692574 20.658687,10.945585 17.543179,15.051507 13.020442,21.012013 7.910957,27.325787 6.7103942,34.711004 6.0558895,38.737163 6.434461,43.510925 8.917073,46.747431 c 3.604523,4.699107 15.24614,7.62307 16.048569,7.62307 0.802429,0 8.366957,0.46766 12.036427,-1.203642 2.841316,-1.294111 5.173945,-3.766846 6.820641,-6.419428 2.543728,-4.097563 3.563068,-9.062928 4.21275,-13.841891 C 49.107723,25.018147 48.401726,15.967648 47.433639,9.0332932 47.09109,6.5796321 43.508442,7.2266282 42.329009,5.7211058 41.256823,4.3524824 42.197481,1.860825 40.813604,0.80840168 40.384481,0.48205899 39.716131,0.42556727 39.208747,0.60779459 37.650593,1.1674066 37.318797,3.5633724 35.798426,4.2187227 z"\ style="fill:none;fill-opacity:1;stroke:%s;stroke-width:3.0" />\ </g>' % ( scale, scale, self._colors[1]) def _gradient(self, r, cx, cy): scale = (DOT_SIZE * self._scale) / 55. return '\ <defs>\ <linearGradient\ id="linearGradient3769">\ <stop\ id="stop3771"\ style="stop-color:#ffff00;stop-opacity:1"\ offset="0" />\ <stop\ id="stop3773"\ style="stop-color:#ffff00;stop-opacity:0"\ offset="1" />\ </linearGradient>\ <linearGradient\ x1="10.761448"\ y1="41.003559"\ x2="56.70686"\ y2="41.003559"\ id="linearGradient2999"\ xlink:href="#linearGradient3769"\ gradientUnits="userSpaceOnUse"\ gradientTransform="matrix(0.93094239,0,0,0.93094239,-3.9217825,-2.4013121)" />\ </defs>\ <g transform="matrix(%f,0,0,%f,0,0)">\ <path\ d="m 35.798426,4.2187227 c -2.210658,0.9528967 -4.993612,-0.9110169 -7.221856,0 C 23.805784,6.1692574 20.658687,10.945585 17.543179,15.051507 13.020442,21.012013 7.910957,27.325787 6.7103942,34.711004 6.0558895,38.737163 6.434461,43.510925 8.917073,46.747431 c 3.604523,4.699107 15.24614,7.62307 16.048569,7.62307 0.802429,0 8.366957,0.46766 12.036427,-1.203642 2.841316,-1.294111 5.173945,-3.766846 6.820641,-6.419428 2.543728,-4.097563 3.563068,-9.062928 4.21275,-13.841891 C 49.107723,25.018147 48.401726,15.967648 47.433639,9.0332932 47.09109,6.5796321 43.508442,7.2266282 42.329009,5.7211058 41.256823,4.3524824 42.197481,1.860825 40.813604,0.80840168 40.384481,0.48205899 39.716131,0.42556727 39.208747,0.60779459 37.650593,1.1674066 37.318797,3.5633724 35.798426,4.2187227 z"\ style="fill:#fffec2;fill-opacity:1;stroke:#878600;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />\ <path\ d="m 15.11608,18.808876 c 1.271657,-1.444003 4.153991,-3.145785 5.495465,-1.7664 2.950062,3.033434 -6.07961,8.17155 -4.219732,11.972265 0.545606,1.114961 2.322391,1.452799 3.532799,1.177599 5.458966,-1.241154 6.490591,-12.132334 12.070397,-11.677864 1.584527,0.129058 2.526156,2.269906 2.845867,3.827199 0.453143,2.207236 -1.962667,6.182399 -1.570133,6.574932 0.392533,0.392533 2.371401,0.909584 3.140266,0.196266 1.91857,-1.779962 -0.490667,-7.752531 0.09813,-7.850664 0.5888,-0.09813 4.421663,2.851694 5.789865,5.004799 0.583188,0.917747 -0.188581,2.956817 0.8832,3.140266 2.128963,0.364398 1.601562,-5.672021 3.729066,-5.299199 1.836829,0.321884 1.450925,3.532631 1.471999,5.397332 0.06743,5.965698 -0.565586,12.731224 -4.317865,17.369596 -3.846028,4.75426 -10.320976,8.31978 -16.388263,7.556266 C 22.030921,53.720741 16.615679,52.58734 11.485147,49.131043 7.9833717,46.771994 6.8028191,42.063042 6.5784815,37.846738 6.3607378,33.754359 8.3381535,29.765466 10.111281,26.070741 c 1.271951,-2.650408 2.940517,-4.917813 5.004799,-7.261865 z"\ style="fill:url(#linearGradient2999);fill-opacity:1;stroke:none" />\ <path\ d="m 32.382709,4.7758124 c -0.123616,1.0811396 1.753928,2.8458658 2.728329,2.9439992 0.974405,0.098134 6.718874,0.7298319 9.159392,-0.1962668 0.820281,-0.3112699 0.968884,-0.9547989 0.974407,-1.4719993 0.02053,-1.9240971 0.03247,-4.7715376 -3.507853,-5.49546551 C 39.556079,0.11012647 37.217081,1.4131653 35.500801,2.2243463 34.054814,2.9077752 32.496703,3.7788369 32.382709,4.7758124 z"\ style="fill:#b69556;fill-opacity:1;stroke:#b69556;stroke-width:1.31189477px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /></g>' % ( scale, scale) def _def(self, r): return ' <defs>\ <linearGradient\ id="linearGradient3755">\ <stop\ id="stop3757"\ style="stop-color:%s;stop-opacity:1"\ offset="0" />\ <stop\ id="stop3759"\ style="stop-color:%s;stop-opacity:1"\ offset="1" />\ </linearGradient>\ <radialGradient\ cx="0"\ cy="0"\ r="%f"\ fx="%f"\ fy="%f"\ id="radialGradient3761"\ xlink:href="#linearGradient3755"\ gradientUnits="userSpaceOnUse" />\ </defs>\ ' % (self._fill, self._fill_dark, r, r / 3, r / 3) def _footer(self): return '</svg>\n'
class Game(): def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = [colors[0]] self._colors.append(colors[1]) self._colors.append('#D0D0D0') self._colors.append('#000000') self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._width / (10 * DOT_SIZE * 1.2) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self.we_are_sharing = False self._edge = 4 self._move_list = [] # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] self._generate_grid() def _generate_grid(self): ''' Make a new set of dots for a grid of size edge ''' i = 0 for y in range(self._edge): for x in range(self._edge): xoffset = int((self._width - self._edge * self._dot_size - \ (self._edge - 1) * self._space) / 2.) if i < len(self._dots): self._dots[i].move( (xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space))) else: self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space), self._new_dot(self._colors[0]))) self._dots[i].type = 0 self._dots[-1].set_label_attributes(40) i += 1 # and initialize a few variables we'll need. self._all_clear() def _all_clear(self): ''' Things to reinitialize when starting up a new game. ''' self._move_list = [] # Clear dots for dot in self._dots: dot.type = 0 dot.set_shape(self._new_dot(self._colors[0])) dot.set_label('') def _initiating(self): return self._activity.initiating def more_dots(self): ''' Enlarge the grid ''' if self._edge < MAX: self._edge += 1 self._generate_grid() self.new_game() def new_game(self): ''' Start a new game. ''' self._all_clear() # Fill in a few dots to start for i in range(MAX * 2): self._flip_them(int(uniform(0, self._edge * self._edge))) if self.we_are_sharing: _logger.debug('sending a new game') self._parent.send_new_game() def restore_game(self, dot_list, move_list): ''' Restore a game from the Journal or share ''' edge = int(sqrt(len(dot_list))) if edge > MAX: edge = MAX while self._edge < edge: self.more_dots() for i, dot in enumerate(dot_list): self._dots[i].type = dot self._dots[i].set_shape( self._new_dot(self._colors[self._dots[i].type])) if move_list is not None: self._move_list = move_list[:] def save_game(self): ''' Return dot list, move_list for saving to Journal or sharing ''' dot_list = [] for dot in self._dots: dot_list.append(dot.type) return (dot_list, self._move_list) def _set_label(self, string): ''' Set the label in the toolbar or the window frame. ''' self._activity.status.set_label(string) def _button_press_cb(self, win, event): win.grab_focus() x, y = map(int, event.get_coords()) spr = self._sprites.find_sprite((x, y)) if spr == None: return if spr.type is not None: self._flip_them(self._dots.index(spr)) self._test_game_over() if self.we_are_sharing: _logger.debug('sending a click to the share') self._parent.send_dot_click(self._dots.index(spr)) return True def solve(self): ''' Solve the puzzle by undoing moves ''' if self._move_list == []: return self._flip_them(self._move_list.pop(), append=False) GObject.timeout_add(750, self.solve) def _flip_them(self, dot, append=True): ''' flip the dot and its neighbors ''' if append: self._move_list.append(dot) x, y = self._dot_to_grid(dot) self._flip(self._dots[dot]) if x > 0: self._flip(self._dots[dot - 1]) if y > 0: self._flip(self._dots[dot - self._edge]) if x < self._edge - 1: self._flip(self._dots[dot + 1]) if y < self._edge - 1: self._flip(self._dots[dot + self._edge]) def _flip(self, spr): ''' flip a dot ''' spr.type += 1 spr.type %= 2 spr.set_shape(self._new_dot(self._colors[spr.type])) def remote_button_press(self, dot): ''' Receive a button press from a sharer ''' self._flip_them(dot) self._test_game_over() def set_sharing(self, share=True): _logger.debug('enabling sharing') self.we_are_sharing = share def _smile(self): for dot in self._dots: dot.set_label(':)') def _test_game_over(self): ''' Check to see if game is over: all dots the same color ''' match = self._dots[0].type for y in range(self._edge): for x in range(self._edge): if self._dots[y * self._edge + x].type != match: self._set_label(_('keep trying')) return False self._set_label(_('good work')) self._smile() GObject.timeout_add(2000, self.more_dots) return True def _grid_to_dot(self, pos): ''' calculate the dot index from a column and row in the grid ''' return pos[0] + pos[1] * self._edge def _dot_to_grid(self, dot): ''' calculate the grid column and row for a dot ''' return [dot % self._edge, int(dot / self._edge)] def game_over(self, msg=_('Game over')): ''' Nothing left to do except show the results. ''' self._set_label(msg) def __draw_cb(self, canvas, cr): self._sprites.redraw_sprites(cr=cr) def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self._canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit() def _new_dot(self, color): ''' generate a dot of a color color ''' self._dot_cache = {} if not color in self._dot_cache: self._stroke = color self._fill = color self._svg_width = self._dot_size self._svg_height = self._dot_size pixbuf = svg_str_to_pixbuf( self._header() + \ self._circle(self._dot_size / 2., self._dot_size / 2., self._dot_size / 2.) + \ self._footer()) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self._svg_width, self._svg_height) context = cairo.Context(surface) Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0) context.rectangle(0, 0, self._svg_width, self._svg_height) context.fill() self._dot_cache[color] = surface return self._dot_cache[color] def _header(self): return '<svg\n' + 'xmlns:svg="http://www.w3.org/2000/svg"\n' + \ 'xmlns="http://www.w3.org/2000/svg"\n' + \ 'xmlns:xlink="http://www.w3.org/1999/xlink"\n' + \ 'version="1.1"\n' + 'width="' + str(self._svg_width) + '"\n' + \ 'height="' + str(self._svg_height) + '">\n' def _circle(self, r, cx, cy): return '<circle style="fill:' + str(self._fill) + ';stroke:' + \ str(self._stroke) + ';" r="' + str(r - 0.5) + '" cx="' + \ str(cx) + '" cy="' + str(cy) + '" />\n' def _footer(self): return '</svg>\n'
class Game(): def __init__(self, canvas, parent=None, path=None): self._canvas = canvas self._parent = parent self._parent.show_all() self._path = path self._canvas.connect("draw", self.__draw_cb) self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("button-press-event", self._button_press_cb) self._canvas.add_events(Gdk.EventMask.POINTER_MOTION_MASK) self._canvas.connect("motion-notify-event", self._mouse_move_cb) self._canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK) self._canvas.connect('button-release-event', self._button_release_cb) self._canvas.add_events(Gdk.EventMask.KEY_PRESS_MASK) self._canvas.connect('key-press-event', self._keypress_cb) self._canvas.set_can_focus(True) self._canvas.grab_focus() self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() self._scale = self._width / 1200. self._first_time = True self._loco_pos = (0, 0) self._loco_dim = (0, 0) self._loco_quadrant = 3 self._drag_pos = [0, 0] self._counter = 0 self._correct = 0 self._timeout_id = None self._pause = 200 self._press = None self._clicked = False self._dead_key = None self._waiting_for_delete = False self._waiting_for_enter = False self._seconds = 0 self._timer_id = None self.level = 0 self.score = 0 # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._BG = ['background0.jpg', 'background0.jpg', 'background0.jpg', 'background1.jpg', 'background2.jpg', 'background2.jpg', 'background2.jpg'] self._backgrounds = [] for bg in self._BG: self._backgrounds.append(Sprite( self._sprites, 0, 0, GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', bg), self._width, self._height))) self._backgrounds[-1].type = 'background' self._backgrounds[-1].hide() self._panel = Sprite( self._sprites, int(400 * self._scale), int(400 * self._scale), GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'ventana.png'), int(720 * self._scale), int(370 * self._scale))) self._panel.type = 'panel' self._panel.set_label(LABELS[0]) self._panel.set_label_attributes(20) self._panel.hide() self._LOCOS = glob.glob( os.path.join(self._path, 'images', 'loco*.png')) self._loco_cards = [] for loco in self._LOCOS: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( loco, int(150 * self._scale), int(208 * self._scale)) self._loco_cards.append(Sprite(self._sprites, 0, 0, pixbuf)) self._loco_cards[-1].type = 'loco' self._loco_dim = (int(150 * self._scale), int(208 * self._scale)) self._MEN = glob.glob( os.path.join(self._path, 'images', 'man*.png')) self._man_cards = [] for loco in self._MEN: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( loco, int(150 * self._scale), int(208 * self._scale)) self._man_cards.append(Sprite(self._sprites, 0, 0, pixbuf)) self._man_cards[-1].type = 'loco' self._TAUNTS = glob.glob( os.path.join(self._path, 'images', 'taunt*.png')) self._taunt_cards = [] for loco in self._TAUNTS: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( loco, int(150 * self._scale), int(208 * self._scale)) self._taunt_cards.append(Sprite(self._sprites, 0, 0, pixbuf)) self._taunt_cards[-1].type = 'loco' self._GHOSTS = glob.glob( os.path.join(self._path, 'images', 'ghost*.png')) self._ghost_cards = [] for loco in self._GHOSTS: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( loco, int(150 * self._scale), int(208 * self._scale)) self._ghost_cards.append(Sprite(self._sprites, 0, 0, pixbuf)) self._ghost_cards[-1].type = 'loco' self._sticky_cards = [] self._loco_pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( self._LOCOS[0], int(150 * self._scale), int(208 * self._scale)) self._man_pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( self._MEN[0], int(150 * self._scale), int(208 * self._scale)) self._ghost_pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( self._GHOSTS[0], int(150 * self._scale), int(208 * self._scale)) for i in range(len(MSGS[1])): # Check re i18n self._sticky_cards.append(Sprite(self._sprites, 0, 0, self._loco_pixbuf)) self._sticky_cards[-1].type = 'loco' self._sticky_cards[-1].set_label_attributes(24, vert_align='bottom') self._all_clear() def _time_increment(self): ''' Track seconds since start_time. ''' self._seconds = int(GObject.get_current_time() - self._start_time) self.timer_id = GObject.timeout_add(1000, self._time_increment) def _timer_reset(self): ''' Reset the timer for each level ''' self._start_time = GObject.get_current_time() if self._timer_id is not None: GObject.source_remove(self._timer_id) self._timer_id = None self.score += self._seconds self._time_increment() def _all_clear(self): ''' Things to reinitialize when starting up a new game. ''' for p in self._loco_cards: p.hide() for p in self._man_cards: p.hide() for p in self._taunt_cards: p.hide() for p in self._ghost_cards: p.hide() for p in self._sticky_cards: p.set_shape(self._loco_pixbuf) p.set_label('') p.set_label_color('white') p.hide() self._backgrounds[self.level].set_layer(BG_LAYER) def _show_time(self): self.level = 0 self._all_clear() x = int(self._width / 4.) y = int(self._height / 8.) for i in range(len(str(self.score))): self._sticky_cards[i].move((x, y)) self._sticky_cards[i].set_layer(LOCO_LAYER) self._sticky_cards[i].set_label(str(self.score)[i]) x += int(self._loco_dim[0] / 2.) self.score = 0 self._parent.unfullscreen() GObject.idle_add(play_audio_from_file, self, os.path.join( self._path, 'sounds', 'sonar.ogg')) GObject.timeout_add(5000, self.new_game, True) def new_game(self, first_time): ''' Start a new game at the current level. ''' self._first_time = first_time self._clicked = False # It may be time to advance to the next level. if (self.level == 6 and self._counter == len(MSGS)) or \ self._counter > 4: self._first_time = True self.level += 1 self._counter = 0 self._correct = 0 self._pause = 200 if self.level == len(self._backgrounds): self._show_time() return self._all_clear() if self._first_time: # Every game starts by putting up a panel with instructions # The panel disappears on mouse movement self._panel.set_label(LABELS[self.level]) self._panel.set_layer(PANEL_LAYER) play_audio_from_file(self, os.path.join( self._path, 'sounds', 'drip.ogg')) self._timer_reset() if self.level == 0: # Choose a random location for the Loco self._loco_quadrant += int(uniform(1, 4)) self._loco_quadrant %= 4 x, y = self._quad_to_xy(self._loco_quadrant) play_audio_from_file(self, os.path.join( self._path, 'sounds', 'bark.ogg')) self._loco_cards[0].move((x, y)) self._loco_pos = (x, y) elif self.level == 1: play_audio_from_file(self, os.path.join( self._path, 'sounds', 'glass.ogg')) elif self.level == 2: play_audio_from_file(self, os.path.join( self._path, 'sounds', 'glass.ogg')) # Place some Locos on the canvas for i in range(self._counter + 1): self._loco_quadrant += int(uniform(1, 4)) self._loco_quadrant %= 4 x, y = self._quad_to_xy(self._loco_quadrant) self._sticky_cards[i].move((x, y)) self._sticky_cards[i].type = 'loco' self._sticky_cards[i].set_layer(LOCO_LAYER) elif self.level == 3: play_audio_from_file(self, os.path.join( self._path, 'sounds', 'bark.ogg')) # Place some Locos on the left-side of the canvas for i in range(self._counter + 1): self._loco_quadrant = int(uniform(2, 4)) x, y = self._quad_to_xy(self._loco_quadrant) self._sticky_cards[i].move((x, y)) self._sticky_cards[i].type = 'loco' self._sticky_cards[i].set_layer(LOCO_LAYER) elif self.level == 4: # Place some Locos on the canvas with letters as labels # Just lowercase for i in range(self._counter + 1): self._loco_quadrant = int(uniform(0, 4)) x, y = self._quad_to_xy(self._loco_quadrant) self._sticky_cards[i].move((x, y)) self._sticky_cards[i].type = 'loco' self._sticky_cards[i].set_layer(LOCO_LAYER) self._sticky_cards[i].set_label( ALPHABETLC[int(uniform(0, len(ALPHABETLC)))]) elif self.level == 5: # Place some Locos on the canvas with letters as labels # Uppercase for i in range(self._counter + 1): self._loco_quadrant = int(uniform(0, 4)) x, y = self._quad_to_xy(self._loco_quadrant) self._sticky_cards[i].move((x, y)) self._sticky_cards[i].type = 'loco' self._sticky_cards[i].set_layer(LOCO_LAYER) self._sticky_cards[i].set_label( ALPHABETUC[int(uniform(0, len(ALPHABETUC)))]) elif self.level == 6: x = 0 y = 0 c = 0 for i in range(len(MSGS[self._counter])): if MSGS[self._counter][i] == ' ': y += self._loco_dim[1] x = 0 else: self._sticky_cards[c].move((x, y)) self._sticky_cards[c].type = i self._sticky_cards[c].set_layer(LOCO_LAYER) self._sticky_cards[c].set_label(MSGS[self._counter][i]) c += 1 x += int(self._loco_dim[0] / 2.) if self.level in [0, 1]: self._loco_quadrant += int(uniform(1, 4)) self._loco_quadrant %= 4 x, y = self._quad_to_xy(self._loco_quadrant) if self.level == 0: self._move_loco(x, y, 0) else: self._taunt(x, y, 0) def _quad_to_xy(self, q): x = int(max(0, (self._width / 2.) * uniform(0, 1) - self._loco_dim[0])) if q in [0, 1]: x += int(self._width / 2.) y = int(max(0, (self._height / 2.) * uniform(0, 1) - self._loco_dim[1])) if q in [1, 2]: y += int(self._height / 2.) return x, y def _taunt(self, x, y, i): n = len(self._taunt_cards) self._taunt_cards[(i + 1) % n].hide() if self._clicked: self._timeout_id = None return True else: self._taunt_cards[i % n].move((x, y)) self._taunt_cards[i % n].set_layer(LOCO_LAYER) self._timeout_id = GObject.timeout_add( 200, self._taunt, x, y, i + 1) def _move_loco(self, x, y, i): j = (i + 1) % len(self._loco_cards) cx, cy = self._loco_cards[i].get_xy() dx = cx - x dy = cy - y if dx * dx + dy * dy < 100: self._loco_cards[j].move((x, y)) self._loco_pos = (x, y) self._loco_cards[j].hide() self._loco_cards[i].hide() self._man_cards[0].move((x, y)) self._man_cards[0].set_layer(LOCO_LAYER) self._timeout_id = None if self._pause > 50: self._pause -= 10 return True else: if dx > 0: cx -= 5 elif dx < 0: cx += 5 if dy > 0: cy -= 5 elif dy < 0: cy += 5 self._loco_cards[j].move((cx, cy)) self._loco_pos = (cx, cy) self._loco_cards[j].set_layer(LOCO_LAYER) self._loco_cards[i].hide() self._timeout_id = GObject.timeout_add( self._pause, self._move_loco, x, y, j) def _keypress_cb(self, area, event): ''' Keypress ''' # Games 4, 5, and 6 use the keyboard print 'keypress event' if self.level not in [4, 5, 6]: return True k = Gdk.keyval_name(event.keyval) u = Gdk.keyval_to_unicode(event.keyval) if self._waiting_for_enter: if k == 'Return': self._waiting_for_enter = False self._panel.hide() self._counter += 1 self._correct = 0 GObject.timeout_add(1000, self.new_game, False) return if k in NOISE_KEYS or k in WHITE_SPACE: return True if self.level == 6 and self._waiting_for_delete: if k in ['BackSpace', 'Delete']: self._waiting_for_delete = False self._sticky_cards[self._correct].set_label_color('white') self._sticky_cards[self._correct].set_label( MSGS[self._counter][ self._sticky_cards[self._correct].type]) self._panel.hide() self._panel.set_label_color('black') return if k[0:5] == 'dead_': self._dead_key = k[5:] return if self.level == 6: n = len(MSGS[self._counter]) else: n = self._counter + 1 if self.level == 6: i = self._correct if self._dead_key is not None: k = DEAD_DICTS[DEAD_KEYS.index(self._dead_key)][k] self._dead_key = None elif k in PUNCTUATION: k = PUNCTUATION[k] elif k in SPECIAL: k = SPECIAL[k] elif len(k) > 1: return True if self._sticky_cards[i].labels[0] == k: self._sticky_cards[i].set_label_color('blue') self._sticky_cards[i].set_label(k) self._correct += 1 else: self._sticky_cards[i].set_label_color('red') self._sticky_cards[i].set_label(k) self._panel.set_label_color('red') self._panel.set_label(ALERTS[1]) self._panel.set_layer(PANEL_LAYER) self._waiting_for_delete = True play_audio_from_file(self, os.path.join( self._path, 'sounds', 'glass.ogg')) else: for i in range(n): if self._sticky_cards[i].labels[0] == k: self._sticky_cards[i].set_label('') self._sticky_cards[i].hide() break # Test for end condition if self.level == 6 and \ self._correct == len(MSGS[self._counter]) - \ MSGS[self._counter].count(' '): c = 0 for i in range(len(MSGS[self._counter])): if MSGS[self._counter][i] == ' ': continue elif MSGS[self._counter][i] != self._sticky_cards[c].labels[0]: return True c += 1 self._panel.set_label(ALERTS[0]) self._panel.set_layer(PANEL_LAYER) self._waiting_for_enter = True GObject.idle_add(play_audio_from_file, self, os.path.join( self._path, 'sounds', 'drip.ogg')) return else: for i in range(n): if len(self._sticky_cards[i].labels[0]) > 0: return True self._counter += 1 self._correct = 0 GObject.timeout_add(1000, self.new_game, False) def _mouse_move_cb(self, win, event): ''' Move the mouse. ''' # Games 0, 3, 4, and 5 use move events x, y = map(int, event.get_coords()) if self._seconds > 1: self._panel.hide() if not self._clicked and self.level == 0: # For Game 0, see if the mouse is on the Loco dx = x - self._loco_pos[0] - self._loco_dim[0] / 2. dy = y - self._loco_pos[1] - self._loco_dim[1] / 2. if dx * dx + dy * dy < 200: self._clicked = True if self._timeout_id is not None: GObject.source_remove(self._timeout_id) # Play again self._all_clear() self._man_cards[0].move((x - int(self._loco_dim[0] / 2.), y - int(self._loco_dim[1] / 2.))) self._man_cards[0].set_layer(LOCO_LAYER) self._correct += 1 self._counter += 1 GObject.timeout_add(1000, self.new_game, False) elif self.level in [4, 5]: # For Game 4 and 5, we allow dragging if self._press is None: self._drag_pos = [0, 0] return True dx = x - self._drag_pos[0] dy = y - self._drag_pos[1] self._press.move_relative((dx, dy)) self._drag_pos = [x, y] elif self.level == 3: # For Game 3, we are dragging if self._press is None: self._drag_pos = [0, 0] return True dx = x - self._drag_pos[0] dy = y - self._drag_pos[1] self._press.move_relative((dx, dy)) self._drag_pos = [x, y] if x > self._width / 2.: self._press.set_shape(self._man_pixbuf) if self._press.type == 'loco': self._correct += 1 self._press.type = 'man' return True def _button_release_cb(self, win, event): # Game 3 uses release if self.level == 3: # Move to release if self._correct == self._counter + 1: self._counter += 1 self._correct = 0 GObject.timeout_add(2000, self.new_game, False) self._press = None self._drag_pos = [0, 0] return True def _button_press_cb(self, win, event): self._press = None x, y = map(int, event.get_coords()) if self.level == 0: return spr = self._sprites.find_sprite((x, y)) if spr is None: return if spr.type != 'loco': return if self.level < 2 and self._timeout_id is None: return if self._clicked: return # Games 1, 2, and 3 involve clicks; Games 4 and 5 allow click to drag if self.level == 1: self._all_clear() self._man_cards[0].move((x - int(self._loco_dim[0] / 2.), y - int(self._loco_dim[1] / 2.))) self._man_cards[0].set_layer(LOCO_LAYER) self._clicked = True self._counter += 1 self._correct += 1 if self._timeout_id is not None: GObject.source_remove(self._timeout_id) GObject.timeout_add(2000, self.new_game, False) elif self.level == 2: spr.set_shape(self._ghost_pixbuf) spr.type = 'ghost' if self._correct == self._counter: self._counter += 1 self._correct = 0 GObject.timeout_add(2000, self.new_game, False) else: self._correct += 1 elif self.level in [3, 4, 5]: # In Games 4 and 5, dragging is used to remove overlaps self._press = spr self._drag_pos = [x, y] return True def __draw_cb(self, canvas, cr): self._sprites.redraw_sprites(cr=cr) def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self._canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit()
class Game(): def __init__(self, canvas, parent=None, path=None): self._canvas = canvas self._parent = parent self._parent.show_all() self._path = path self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() self._scale = self._width / 1200. self._target = 0 self._tries = 0 self.level = 0 self._picture_cards = [] self._small_picture_cards = [] self.food_cards = [] self._group_cards = [] self._quantity_cards = [] self._balance_cards = [] self._last_twenty = [] self._background = None # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._background = Sprite( self._sprites, 0, 0, GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'background.png'), self._width, self._height)) self._background.set_layer(0) self._background.type = None self._background.hide() self.pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'word-box.png'), int(350 * self._scale), int(100 * self._scale)) for i in range(len(FOOD_DATA) / 4): FOOD.append([ FOOD_DATA[i * 4 + NAME], FOOD_DATA[i * 4 + CALS], FOOD_DATA[i * 4 + GROUP], FOOD_DATA[i * 4 + IMAGE] ]) self.food_cards.append(None) self._picture_cards.append(None) for j in range(6): self._small_picture_cards.append(None) self.allocate_food(0) x = 10 dx, dy = self.food_cards[0].get_dimensions() y = 10 for i in range(len(MYPLATE)): self.word_card_append(self._group_cards, self.pixbuf) self._group_cards[-1].type = i self._group_cards[-1].set_label(MYPLATE[i][0]) self._group_cards[-1].move((x, y)) y += int(dy * 1.25) y = 10 for i in range(len(QUANTITIES)): self.word_card_append(self._quantity_cards, self.pixbuf) self._quantity_cards[-1].type = i self._quantity_cards[-1].set_label(QUANTITIES[i]) self._quantity_cards[-1].move((x, y)) y += int(dy * 1.25) y = 10 for i in range(len(BALANCE)): self.word_card_append(self._balance_cards, self.pixbuf) self._balance_cards[-1].type = i self._balance_cards[-1].set_label(BALANCE[i]) self._balance_cards[-1].move((x, y)) y += int(dy * 1.25) self._smile = Sprite( self._sprites, int(self._width / 4), int(self._height / 4), GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'correct.png'), int(self._width / 2), int(self._height / 2))) self._smile.set_label_attributes(36) self._smile.set_margins(10, 0, 10, 0) self._frown = Sprite( self._sprites, int(self._width / 4), int(self._height / 4), GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'wrong.png'), int(self._width / 2), int(self._height / 2))) self._frown.set_label_attributes(36) self._frown.set_margins(10, 0, 10, 0) self.build_food_groups() self._all_clear() def allocate_food(self, i): self.picture_append( os.path.join(self._path, 'images', FOOD_DATA[i * 4 + IMAGE]), i) self.small_picture_append( os.path.join(self._path, 'images', FOOD_DATA[i * 4 + IMAGE]), i) self.word_card_append(self.food_cards, self.pixbuf, i) self.food_cards[i].type = i self.food_cards[i].set_label(FOOD_DATA[i * 4 + NAME]) def word_card_append(self, card_list, pixbuf, i=-1): if i == -1: card_list.append(Sprite(self._sprites, 10, 10, pixbuf)) else: card_list[i] = Sprite(self._sprites, 10, 10, pixbuf) card_list[i].set_label_attributes(36) card_list[i].set_margins(10, 0, 10, 0) card_list[i].hide() def picture_append(self, path, i=-1): spr = Sprite( self._sprites, int(self._width / 2.), int(self._height / 4.), GdkPixbuf.Pixbuf.new_from_file_at_size(path, int(self._width / 3.), int(9 * self._width / 12.))) if i == -1: self._picture_cards.append(spr) else: self._picture_cards[i] = spr self._picture_cards[i].type = 'picture' self._picture_cards[i].hide() def small_picture_append(self, path, i=-1): x = int(self._width / 3.) y = int(self._height / 6.) pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( path, int(self._width / 6.), int(3 * self._width / 8.)) for j in range(6): # up to 6 of each card if i == -1: self._small_picture_cards.append( Sprite(self._sprites, x, y, pixbuf)) self._small_picture_cards[-1].type = 'picture' self._small_picture_cards[-1].hide() else: self._small_picture_cards[i * 6 + j] = Sprite( self._sprites, x, y, pixbuf) self._small_picture_cards[i * 6 + j].type = 'picture' self._small_picture_cards[i * 6 + j].hide() x += int(self._width / 6.) if j == 2: x = int(self._width / 3.) y += int(3 * self._width / 16.) def _all_clear(self): ''' Things to reinitialize when starting up a new game. ''' for p in self._picture_cards: if p is not None: p.hide() for p in self._small_picture_cards: if p is not None: p.hide() for i, w in enumerate(self.food_cards): if w is not None: w.set_label_color('black') w.set_label(FOOD[i][NAME]) w.hide() for i, w in enumerate(self._group_cards): w.set_label_color('black') w.set_label(MYPLATE[i][0]) w.hide() for i, w in enumerate(self._quantity_cards): w.set_label_color('black') w.set_label(QUANTITIES[i]) w.hide() for i, w in enumerate(self._balance_cards): w.set_label_color('black') w.set_label(BALANCE[i]) w.hide() self._smile.hide() self._frown.hide() self._background.set_layer(1) def build_food_groups(self): self._my_plate = [[], [], [], []] for i, food in enumerate(FOOD): self._my_plate[MYPLATE[food[GROUP]][QUANT]].append(i) def new_game(self): ''' Start a new game. ''' games = { 0: self._name_that_food, 1: self._name_that_food_group, 2: self._compare_calories, 3: self._how_much_to_eat, 4: self._balanced_meal } self._all_clear() games[self.level]() self._frown.set_label('') self._smile.set_label('') self._tries = 0 def _name_that_food(self): ''' Choose food cards and one matching food picture ''' x = 10 y = 10 dx, dy = self.food_cards[0].get_dimensions() # Select some cards word_list = [] for i in range(NCARDS): j = int(uniform(0, len(FOOD))) while j in word_list: j = int(uniform(0, len(FOOD))) word_list.append(j) # Show the word cards from the list for i in word_list: if self.food_cards[i] is None: self.allocate_food(i) self.food_cards[i].set_layer(100) self.food_cards[i].move((x, y)) y += int(dy * 1.25) # Choose a random food image from the list and show it. self._target = self.food_cards[word_list[int(uniform(0, NCARDS))]].type while self._target in self._last_twenty: self._target = self.food_cards[word_list[int(uniform( 0, NCARDS))]].type self._last_twenty.append(self._target) if len(self._last_twenty) > 20: self._last_twenty.remove(self._last_twenty[0]) self._picture_cards[self._target].set_layer(100) def _name_that_food_group(self): ''' Show group cards and one food picture ''' for i in range(len(MYPLATE)): self._group_cards[i].set_layer(100) # Choose a random food image and show it. self._target = int(uniform(0, len(FOOD))) if self.food_cards[self._target] is None: self.allocate_food(self._target) self._picture_cards[self._target].set_layer(100) def _compare_calories(self): ''' Choose food cards and compare the calories ''' x = 10 y = 10 dx, dy = self.food_cards[0].get_dimensions() # Select some cards word_list = [] for i in range(6): j = int(uniform(0, len(FOOD))) while j in word_list: j = int(uniform(0, len(FOOD))) word_list.append(j) if self.food_cards[j] is None: self.allocate_food(j) # Show the word cards from the list for i in word_list: self.food_cards[i].set_layer(100) self.food_cards[i].move((x, y)) y += int(dy * 1.25) # Show food images self._target = word_list[0] for i in range(5): if FOOD[word_list[i + 1]][CALS] > FOOD[self._target][CALS]: self._target = word_list[i + 1] self._small_picture_cards[word_list[0] * 6].set_layer(100) self._small_picture_cards[word_list[1] * 6 + 1].set_layer(100) self._small_picture_cards[word_list[2] * 6 + 2].set_layer(100) self._small_picture_cards[word_list[3] * 6 + 3].set_layer(100) self._small_picture_cards[word_list[4] * 6 + 4].set_layer(100) self._small_picture_cards[word_list[5] * 6 + 5].set_layer(100) def _how_much_to_eat(self): ''' Show quantity cards and one food picture ''' for i in range(len(QUANTITIES)): self._quantity_cards[i].set_layer(100) # Choose a random image from the list and show it. self._target = int(uniform(0, len(FOOD))) if self.food_cards[self._target] is None: self.allocate_food(self._target) self._picture_cards[self._target].set_layer(100) def _balanced_meal(self): ''' A well-balanced meal ''' for i in range(2): self._balance_cards[i].set_layer(100) # Determine how many foods from each group n = [0, 0, 0, 0] n[0] = int(uniform(0, 2.5)) n[1] = int(uniform(0, 3 - n[0])) n[2] = 3 - n[0] - n[1] n[3] = 6 - n[0] - n[1] - n[2] # Fill a plate with foods from different groups meal = [] for i in range(n[0]): # Sweets j = int(uniform(0, len(self._my_plate[0]))) meal.append(self._my_plate[0][j]) for i in range(n[1]): # Dairy j = int(uniform(0, len(self._my_plate[1]))) meal.append(self._my_plate[1][j]) for i in range(n[2]): # Protein and Fruits j = int(uniform(0, len(self._my_plate[2]))) meal.append(self._my_plate[2][j]) for i in range(n[3]): # Veggies and Grains j = int(uniform(0, len(self._my_plate[3]))) meal.append(self._my_plate[3][j]) if n[0] < 2 and n[1] < 2 and n[2] < n[3]: self._target = 0 # Balanced meal else: self._target = 1 for i in range(6): if self.food_cards[meal[i]] is None: self.allocate_food(meal[i]) # Randomly position small cards self._small_picture_cards[meal[3] * 6].set_layer(100) self._small_picture_cards[meal[4] * 6 + 1].set_layer(100) self._small_picture_cards[meal[1] * 6 + 2].set_layer(100) self._small_picture_cards[meal[2] * 6 + 3].set_layer(100) self._small_picture_cards[meal[5] * 6 + 4].set_layer(100) self._small_picture_cards[meal[0] * 6 + 5].set_layer(100) def _button_press_cb(self, win, event): win.grab_focus() x, y = list(map(int, event.get_coords())) spr = self._sprites.find_sprite((x, y)) if spr == None: return # We only care about clicks on word cards if type(spr.type) != int: return # Which card was clicked? Set its label to red. spr.set_label_color('red') label = spr.labels[0] spr.set_label(label) if self.level == 0: if spr.type == self._target: self._smile.set_layer(200) self._tries = 3 else: self._frown.set_layer(200) self._tries += 1 if self._tries == 3: self.food_cards[self._target].set_label_color('blue') label = self.food_cards[self._target].labels[0] self.food_cards[self._target].set_label(label) elif self.level == 1: i = FOOD[self._target][GROUP] if spr.type == i: self._smile.set_layer(200) self._tries = 3 else: self._frown.set_layer(200) self._tries += 1 if self._tries == 3: self._group_cards[i].set_label_color('blue') label = self._group_cards[i].labels[0] self._group_cards[i].set_label(label) elif self.level == 2: if spr.type == self._target: self._smile.set_layer(200) self._tries = 3 else: self._frown.set_layer(200) self._tries += 1 if self._tries == 3: self.food_cards[self._target].set_label_color('blue') label = self.food_cards[self._target].labels[0] self.food_cards[self._target].set_label(label) elif self.level == 3: i = MYPLATE[FOOD[self._target][GROUP]][QUANT] if spr.type == i: self._smile.set_layer(200) self._tries = 3 else: self._frown.set_layer(200) self._tries += 1 if self._tries == 3: self._quantity_cards[i].set_label_color('blue') label = self._quantity_cards[i].labels[0] self._quantity_cards[i].set_label(label) elif self.level == 4: if self._target == spr.type: self._smile.set_layer(200) self._tries = 3 else: self._frown.set_layer(200) self._tries += 1 if self._tries == 3: self._balance_cards[self._target].set_label_color('blue') label = self._balance_cards[self._target].labels[0] self._balance_cards[self._target].set_label(label) else: _logger.debug('unknown play level %d' % (self.level)) # Play again if self._tries == 3: GObject.timeout_add(2000, self.new_game) else: GObject.timeout_add(1000, self._reset_game) return True def _reset_game(self): self._frown.hide() if self.level in [0, 2]: for i, w in enumerate(self.food_cards): w.set_label_color('black') w.set_label(FOOD[i][NAME]) elif self.level == 1: for i, w in enumerate(self._group_cards): w.set_label_color('black') w.set_label(MYPLATE[i][0]) elif self.level == 3: for i, w in enumerate(self._quantity_cards): w.set_label_color('black') w.set_label(QUANTITIES[i]) elif self.level == 4: for i, w in enumerate(self._balance_cards): w.set_label_color('black') w.set_label(BALANCE[i]) def __draw_cb(self, canvas, cr): self._sprites.redraw_sprites(cr=cr) def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self._canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit()
def __init__(self, canvas, parent=None, path=None): self._canvas = canvas self._parent = parent self._parent.show_all() self._path = path self._canvas.connect("draw", self.__draw_cb) self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("button-press-event", self._button_press_cb) self._canvas.add_events(Gdk.EventMask.POINTER_MOTION_MASK) self._canvas.connect("motion-notify-event", self._mouse_move_cb) self._canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK) self._canvas.connect('button-release-event', self._button_release_cb) self._canvas.add_events(Gdk.EventMask.KEY_PRESS_MASK) self._canvas.connect('key-press-event', self._keypress_cb) self._canvas.set_can_focus(True) self._canvas.grab_focus() self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() self._scale = self._width / 1200. self._first_time = True self._loco_pos = (0, 0) self._loco_dim = (0, 0) self._loco_quadrant = 3 self._drag_pos = [0, 0] self._counter = 0 self._correct = 0 self._timeout_id = None self._pause = 200 self._press = None self._clicked = False self._dead_key = None self._waiting_for_delete = False self._waiting_for_enter = False self._seconds = 0 self._timer_id = None self.level = 0 self.score = 0 # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._BG = ['background0.jpg', 'background0.jpg', 'background0.jpg', 'background1.jpg', 'background2.jpg', 'background2.jpg', 'background2.jpg'] self._backgrounds = [] for bg in self._BG: self._backgrounds.append(Sprite( self._sprites, 0, 0, GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', bg), self._width, self._height))) self._backgrounds[-1].type = 'background' self._backgrounds[-1].hide() self._panel = Sprite( self._sprites, int(400 * self._scale), int(400 * self._scale), GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._path, 'images', 'ventana.png'), int(720 * self._scale), int(370 * self._scale))) self._panel.type = 'panel' self._panel.set_label(LABELS[0]) self._panel.set_label_attributes(20) self._panel.hide() self._LOCOS = glob.glob( os.path.join(self._path, 'images', 'loco*.png')) self._loco_cards = [] for loco in self._LOCOS: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( loco, int(150 * self._scale), int(208 * self._scale)) self._loco_cards.append(Sprite(self._sprites, 0, 0, pixbuf)) self._loco_cards[-1].type = 'loco' self._loco_dim = (int(150 * self._scale), int(208 * self._scale)) self._MEN = glob.glob( os.path.join(self._path, 'images', 'man*.png')) self._man_cards = [] for loco in self._MEN: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( loco, int(150 * self._scale), int(208 * self._scale)) self._man_cards.append(Sprite(self._sprites, 0, 0, pixbuf)) self._man_cards[-1].type = 'loco' self._TAUNTS = glob.glob( os.path.join(self._path, 'images', 'taunt*.png')) self._taunt_cards = [] for loco in self._TAUNTS: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( loco, int(150 * self._scale), int(208 * self._scale)) self._taunt_cards.append(Sprite(self._sprites, 0, 0, pixbuf)) self._taunt_cards[-1].type = 'loco' self._GHOSTS = glob.glob( os.path.join(self._path, 'images', 'ghost*.png')) self._ghost_cards = [] for loco in self._GHOSTS: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( loco, int(150 * self._scale), int(208 * self._scale)) self._ghost_cards.append(Sprite(self._sprites, 0, 0, pixbuf)) self._ghost_cards[-1].type = 'loco' self._sticky_cards = [] self._loco_pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( self._LOCOS[0], int(150 * self._scale), int(208 * self._scale)) self._man_pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( self._MEN[0], int(150 * self._scale), int(208 * self._scale)) self._ghost_pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( self._GHOSTS[0], int(150 * self._scale), int(208 * self._scale)) for i in range(len(MSGS[1])): # Check re i18n self._sticky_cards.append(Sprite(self._sprites, 0, 0, self._loco_pixbuf)) self._sticky_cards[-1].type = 'loco' self._sticky_cards[-1].set_label_attributes(24, vert_align='bottom') self._all_clear()
class Game(): def __init__(self, canvas, path, parent=None): self.activity = parent self.path = path # starting from command line # we have to do all the work that was done in CardSortActivity.py if parent is None: self.sugar = False self.canvas = canvas # starting from Sugar else: self.sugar = True self.canvas = canvas parent.show_all() self.canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self.canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK) self.canvas.connect("draw", self.__draw_cb) self.canvas.connect("button-press-event", self._button_press_cb) self.canvas.connect("button-release-event", self._button_release_cb) self.width = Gdk.Screen.width() self.height = Gdk.Screen.height() - style.GRID_CELL_SIZE self.card_dim = CARD_DIM self.scale = 0.8 * self.height / (self.card_dim * 3) # Initialize the sprite repository self.sprites = Sprites(self.canvas) # Initialize the grid self.grid = Grid(self) # Start solving the puzzle self.press = -1 self.release = -1 self.start_drag = [0, 0] # # Button press # def _button_press_cb(self, win, event): win.grab_focus() x, y = map(int, event.get_coords()) self.start_drag = [x, y] self.grid.hide_masks() spr = self.sprites.find_sprite((x, y)) if spr is None: self.press = -1 self.release = -1 return True # take note of card under button press self.press = int(spr.labels[0]) return True # # Button release # def _button_release_cb(self, win, event): win.grab_focus() self.grid.hide_masks() x, y = map(int, event.get_coords()) spr = self.sprites.find_sprite((x, y)) if spr is None: self.press = -1 self.release = -1 return True # take note of card under button release self.release = int(spr.labels[0]) # if the same card (click) then rotate if self.press == self.release: # check to see if it was an aborted move if self.distance(self.start_drag, [x, y]) < 20: self.grid.card_table[self.press].rotate_ccw() # self.grid.card_table[self.press].print_card() # if different card (drag) then swap else: self.grid.swap(self.press, self.release) # self.grid.print_grid() self.press = -1 self.release = -1 if self.test() is True: if self.sugar is True: self.activity.results_label.set_text( _("You solved the puzzle.")) self.activity.results_label.show() else: self.win.set_title( _("CardSort") + ": " + _("You solved the puzzle.")) else: if self.sugar is True: self.activity.results_label.set_text(_("Keep trying.")) self.activity.results_label.show() else: self.win.set_title(_("CardSort") + ": " + _("Keep trying.")) return True # # Measure length of drag between button press and button release # def distance(self, start, stop): dx = start[0] - stop[0] dy = start[1] - stop[1] return sqrt(dx * dx + dy * dy) # # Repaint # def __draw_cb(self, canvas, cr): self.sprites.redraw_sprites(cr=cr) def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self.canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self.sprites.redraw_sprites(cr=cr) # # callbacks # def _destroy_cb(self, win, event): Gtk.main_quit()
class SlideRule(): def __init__(self, canvas, path, parent=None, sugar=True): """ Handle launch from both within and without of Sugar environment. """ self.SLIDES = {'C':[C_slide_generator], 'CI':[CI_slide_generator], 'A':[A_slide_generator], 'K':[K_slide_generator], 'S':[S_slide_generator], 'T':[T_slide_generator], 'L':[L_slide_generator], 'LLn':[LLn_slide_generator], 'Log':[Log_slide_generator], 'custom':[Custom_slide_generator]} self.STATORS = {'D':[D_stator_generator], 'DI':[DI_stator_generator], 'B':[B_stator_generator], 'K2':[K_stator_generator], 'S2':[S_stator_generator], 'T2':[T_stator_generator], 'L2':[L_stator_generator], 'LLn2':[LLn_stator_generator], 'Log2':[Log_stator_generator], 'custom2':[Custom_stator_generator]} self.path = path self.sugar = sugar self.canvas = canvas self.parent = parent parent.show_all() self.canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self.canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK) self.canvas.add_events(Gdk.EventMask.POINTER_MOTION_MASK) self.canvas.add_events(Gdk.EventMask.KEY_PRESS_MASK) self.canvas.connect("draw", self.__draw_cb) self.canvas.connect("button-press-event", self._button_press_cb) self.canvas.connect("button-release-event", self._button_release_cb) self.canvas.connect("motion-notify-event", self._mouse_move_cb) self.canvas.connect("key-press-event", self._keypress_cb) self.canvas.set_can_focus(True) self.canvas.grab_focus() self.width = Gdk.Screen.width() self.height = Gdk.Screen.height() - GRID_CELL_SIZE self.sprites = Sprites(self.canvas) self.slides = [] self.stators = [] self.scale = 1 locale.setlocale(locale.LC_NUMERIC, '') self.decimal_point = locale.localeconv()['decimal_point'] if self.decimal_point == '' or self.decimal_point is None: self.decimal_point = '.' self.error_msg = None self.result_function = [None, None] self.label_function = [None, None] _logger.debug("creating slides, stators, and reticule") self.result_label = Stator(self.sprites, self.path, 'label', int((self.width - 600) / 2), SCREENOFFSET + 4 * SHEIGHT, 800, SHEIGHT) for slide in self.SLIDES: self.make_slide(slide, SLIDE) for stator in self.STATORS: self.make_slide(stator, STATOR) self.reticule = Reticule(self.sprites, self.path, 'reticule', 150, SCREENOFFSET + SHEIGHT, 100, 2 * SHEIGHT) self.reticule.draw(2000) self.press = None self.last = None self.dragpos = 0 # We need textviews for keyboard input from the on-screen keyboard self._set_screen_dpi() font_desc = Pango.font_description_from_string('12') self.text_entries = [] self.text_buffers = [] w = self.reticule.tabs[0].spr.label_safe_width() h = int(self.reticule.tabs[0].spr.label_safe_height() / 2) for i in range(4): # Reticule top & bottom; Slider left & right self.text_entries.append(Gtk.TextView()) self.text_entries[-1].set_justification(Gtk.Justification.CENTER) self.text_entries[-1].set_pixels_above_lines(4) ''' Not necessary (and doesn't work on OS8) self.text_entries[-1].override_background_color( Gtk.StateType.NORMAL, Gdk.RGBA(0, 0, 0, 0)) ''' self.text_entries[-1].modify_font(font_desc) self.text_buffers.append(self.text_entries[-1].get_buffer()) self.text_entries[-1].set_size_request(w, h) self.text_entries[-1].show() self.parent.fixed.put(self.text_entries[-1], 0, 0) self.parent.fixed.show() self.text_entries[-1].connect('focus-out-event', self._text_focus_out_cb) self.reticule.add_textview(self.text_entries[0], i=BOTTOM) self.reticule.add_textview(self.text_entries[1], i=TOP) self.reticule.set_fixed(self.parent.fixed) for slide in self.slides: slide.add_textview(self.text_entries[2], i=LEFT) slide.add_textview(self.text_entries[3], i=RIGHT) slide.set_fixed(self.parent.fixed) if not self.sugar: self.update_textview_y_offset(self.parent.menu_height) self.active_slide = self.name_to_slide('C') self.active_stator = self.name_to_stator('D') self.update_slide_labels() self.update_result_label() def update_textview_y_offset(self, dy): ''' Need to account for menu height in GNOME ''' self.reticule.tabs[0].textview_y_offset += dy self.reticule.tabs[1].textview_y_offset += dy for slide in self.slides: slide.tabs[0].textview_y_offset += dy slide.tabs[1].textview_y_offset += dy def _text_focus_out_cb(self, widget=None, event=None): ''' One of the four textviews was in focus ''' i = None if widget in self.text_entries: i = self.text_entries.index(widget) bounds = self.text_buffers[i].get_bounds() text = self.text_buffers[i].get_text(bounds[0], bounds[1], True) text = text.strip() self._process_numeric_input(i, text) def _set_screen_dpi(self): dpi = _get_screen_dpi() font_map_default = PangoCairo.font_map_get_default() font_map_default.set_resolution(dpi) def __draw_cb(self, canvas, cr): self.sprites.redraw_sprites(cr=cr) # Handle the expose-event by drawing def do_expose_event(self, event): # Create the cairo context cr = self.canvas.window.cairo_create() print 'set cr in do_expose' self.sprites.set_cairo_context(cr) # Restrict Cairo to the exposed area; avoid extra work cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self.sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit() def _keypress_cb(self, area, event): """ Keypress: moving the slides with the arrow keys """ k = Gdk.keyval_name(event.keyval) if not self.sugar: return if k == 'a': self.parent.show_a() elif k == 'k': self.parent.show_k() elif k in ['c', 'asterisk', 'x']: self.parent.show_c() elif k in ['i', '/']: self.parent.show_ci() elif k == 's': self.parent.show_s() elif k == 't': self.parent.show_t() elif k in ['l', 'plus']: self.parent.show_l() elif k in ['Left', 'less']: if self.last is not None: self._move_slides(self.last, -1) elif k in ['Right', 'greater']: if self.last is not None: self._move_slides(self.last, 1) elif k in ['Home', 'Pause', 'Up', '^']: self._move_slides(self.name_to_stator('D').spr, - self.name_to_stator('D').spr.get_xy()[0]) elif k == 'r': self.reticule.move(150, self.reticule.spr.get_xy()[1]) self.update_slide_labels() self.update_result_label() elif k in ['Down', 'v']: self.parent.realign_cb() self.reticule.move(150, self.reticule.spr.get_xy()[1]) self.update_slide_labels() self.update_result_label() return True def _process_numeric_input(self, i, text): try: n = float(text.replace(self.decimal_point, '.')) if i == 0: self._move_reticule_to_stator_value(n) elif i == 1: self._move_reticule_to_slide_value(n) elif i == 2: self._move_slide_to_stator_value(n) elif i == 3: self._move_slide_to_stator_value(self._left_from_right(n)) except ValueError: self.result_label.spr.labels[0] = _('NaN') + ' ' + text return def _process_text_field(self, text_field): """ Process input from numeric text fields: could be a function. """ try: my_min = "def f(): return " + text_field.replace('import','') userdefined = {} exec my_min in globals(), userdefined return userdefined.values()[0]() except OverflowError, e: self.result_label.spr.labels[0] = _('Overflow Error') + \ ': ' + str(e) self.result_label.draw(1000) except NameError, e: self.result_label.spr.labels[0] = _('Name Error') + ': ' + str(e) self.result_label.draw(1000)
class Game(): def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = [colors[0]] self._colors.append(colors[1]) self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.connect("draw", self.__draw_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._width / (10 * DOT_SIZE * 1.2) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self.max_levels = len(LEVELS_TRUE) self.this_pattern = False # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._dots = [] self._generate_grid() def _generate_grid(self): ''' Make a new set of dots for a grid of size edge ''' i = 0 for y in range(GRID): for x in range(GRID): xoffset = int((self._width - GRID * self._dot_size - (GRID - 1) * self._space) / 2.) if i < len(self._dots): self._dots[i].move( (xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space) + self._space)) else: self._dots.append( Sprite(self._sprites, xoffset + x * (self._dot_size + self._space), y * (self._dot_size + self._space) + self._space, self._new_dot(self._colors[0]))) self._dots[i].type = 0 self._dots[-1].set_label_attributes(40) i += 1 def show(self, dot_list): for i in range(GRID * GRID): self._dots[i].set_shape(self._new_dot(self._colors[dot_list[i]])) self._dots[i].type = dot_list[i] def show_true(self): self.show(self._generate_pattern(LEVELS_TRUE[self._activity.level])) self.this_pattern = True def show_false(self): self.show(self._generate_pattern(LEVELS_FALSE[self._activity.level])) self.this_pattern = False def show_random(self): ''' Fill the grid with a true or false pattern ''' if int(uniform(0, 2)) == 0: self.show_true() else: self.show_false() def _initiating(self): return self._activity._collab.props.leader def new_game(self): ''' Start a new game. ''' self.show_random() def restore_grid(self, dot_list, boolean, color): ''' Restore a grid from the share ''' self.show(dot_list) self.this_pattern = boolean self._colors = color def save_grid(self): ''' Return dot list for sharing ''' dot_list = [] for dot in self._dots: dot_list.append(dot.type) return dot_list, self.this_pattern, self._colors def _grid_to_dot(self, pos): ''' calculate the dot index from a column and row in the grid ''' return pos[0] + pos[1] * GRID def _dot_to_grid(self, dot): ''' calculate the grid column and row for a dot ''' return [dot % GRID, int(dot // GRID)] def _set_label(self, string): ''' Set the label in the toolbar or the window frame. ''' self._activity.status.set_label(string) def _generate_pattern(self, f): ''' Run Python code passed as argument ''' userdefined = {} try: exec(f, globals(), userdefined) return userdefined['generate_pattern'](self) except ZeroDivisionError as e: self._set_label('Python zero-divide error: %s' % (str(e))) except ValueError as e: self._set_label('Python value error: %s' % (str(e))) except SyntaxError as e: self._set_label('Python syntax error: %s' % (str(e))) except NameError as e: self._set_label('Python name error: %s' % (str(e))) except OverflowError as e: self._set_label('Python overflow error: %s' % (str(e))) except TypeError as e: self._set_label('Python type error: %s' % (str(e))) except BaseException: self._set_label('Python error') traceback.print_exc() return None def __draw_cb(self, canvas, cr): self._sprites.redraw_sprites(cr=cr) def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self._canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list if cr is not None: self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit() def _new_dot(self, color): ''' generate a dot of a color color ''' self._dot_cache = {} if color not in self._dot_cache: self._stroke = color self._fill = color self._svg_width = self._dot_size self._svg_height = self._dot_size pixbuf = svg_str_to_pixbuf( self._header() + self._circle(self._dot_size / 2., self._dot_size / 2., self._dot_size / 2.) + self._footer()) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self._svg_width, self._svg_height) context = cairo.Context(surface) Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0) context.rectangle(0, 0, self._svg_width, self._svg_height) context.fill() self._dot_cache[color] = surface return self._dot_cache[color] def _header(self): return '<svg\n' + 'xmlns:svg="http://www.w3.org/2000/svg"\n' + \ 'xmlns="http://www.w3.org/2000/svg"\n' + \ 'xmlns:xlink="http://www.w3.org/1999/xlink"\n' + \ 'version="1.1"\n' + 'width="' + str(self._svg_width) + '"\n' + \ 'height="' + str(self._svg_height) + '">\n' def _circle(self, r, cx, cy): return '<circle style="fill:' + str(self._fill) + ';stroke:' + \ str(self._stroke) + ';" r="' + str(r - 0.5) + '" cx="' + \ str(cx) + '" cy="' + str(cy) + '" />\n' def _footer(self): return '</svg>\n'
def __init__(self, canvas, path, parent=None, sugar=True): """ Handle launch from both within and without of Sugar environment. """ self.SLIDES = {'C':[C_slide_generator], 'CI':[CI_slide_generator], 'A':[A_slide_generator], 'K':[K_slide_generator], 'S':[S_slide_generator], 'T':[T_slide_generator], 'L':[L_slide_generator], 'LLn':[LLn_slide_generator], 'Log':[Log_slide_generator], 'custom':[Custom_slide_generator]} self.STATORS = {'D':[D_stator_generator], 'DI':[DI_stator_generator], 'B':[B_stator_generator], 'K2':[K_stator_generator], 'S2':[S_stator_generator], 'T2':[T_stator_generator], 'L2':[L_stator_generator], 'LLn2':[LLn_stator_generator], 'Log2':[Log_stator_generator], 'custom2':[Custom_stator_generator]} self.path = path self.sugar = sugar self.canvas = canvas self.parent = parent parent.show_all() self.canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self.canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK) self.canvas.add_events(Gdk.EventMask.POINTER_MOTION_MASK) self.canvas.add_events(Gdk.EventMask.KEY_PRESS_MASK) self.canvas.connect("draw", self.__draw_cb) self.canvas.connect("button-press-event", self._button_press_cb) self.canvas.connect("button-release-event", self._button_release_cb) self.canvas.connect("motion-notify-event", self._mouse_move_cb) self.canvas.connect("key-press-event", self._keypress_cb) self.canvas.set_can_focus(True) self.canvas.grab_focus() self.width = Gdk.Screen.width() self.height = Gdk.Screen.height() - GRID_CELL_SIZE self.sprites = Sprites(self.canvas) self.slides = [] self.stators = [] self.scale = 1 locale.setlocale(locale.LC_NUMERIC, '') self.decimal_point = locale.localeconv()['decimal_point'] if self.decimal_point == '' or self.decimal_point is None: self.decimal_point = '.' self.error_msg = None self.result_function = [None, None] self.label_function = [None, None] _logger.debug("creating slides, stators, and reticule") self.result_label = Stator(self.sprites, self.path, 'label', int((self.width - 600) / 2), SCREENOFFSET + 4 * SHEIGHT, 800, SHEIGHT) for slide in self.SLIDES: self.make_slide(slide, SLIDE) for stator in self.STATORS: self.make_slide(stator, STATOR) self.reticule = Reticule(self.sprites, self.path, 'reticule', 150, SCREENOFFSET + SHEIGHT, 100, 2 * SHEIGHT) self.reticule.draw(2000) self.press = None self.last = None self.dragpos = 0 # We need textviews for keyboard input from the on-screen keyboard self._set_screen_dpi() font_desc = Pango.font_description_from_string('12') self.text_entries = [] self.text_buffers = [] w = self.reticule.tabs[0].spr.label_safe_width() h = int(self.reticule.tabs[0].spr.label_safe_height() / 2) for i in range(4): # Reticule top & bottom; Slider left & right self.text_entries.append(Gtk.TextView()) self.text_entries[-1].set_justification(Gtk.Justification.CENTER) self.text_entries[-1].set_pixels_above_lines(4) ''' Not necessary (and doesn't work on OS8) self.text_entries[-1].override_background_color( Gtk.StateType.NORMAL, Gdk.RGBA(0, 0, 0, 0)) ''' self.text_entries[-1].modify_font(font_desc) self.text_buffers.append(self.text_entries[-1].get_buffer()) self.text_entries[-1].set_size_request(w, h) self.text_entries[-1].show() self.parent.fixed.put(self.text_entries[-1], 0, 0) self.parent.fixed.show() self.text_entries[-1].connect('focus-out-event', self._text_focus_out_cb) self.reticule.add_textview(self.text_entries[0], i=BOTTOM) self.reticule.add_textview(self.text_entries[1], i=TOP) self.reticule.set_fixed(self.parent.fixed) for slide in self.slides: slide.add_textview(self.text_entries[2], i=LEFT) slide.add_textview(self.text_entries[3], i=RIGHT) slide.set_fixed(self.parent.fixed) if not self.sugar: self.update_textview_y_offset(self.parent.menu_height) self.active_slide = self.name_to_slide('C') self.active_stator = self.name_to_stator('D') self.update_slide_labels() self.update_result_label()
def __init__(self, canvas, parent=None, colors=['#A0FFA0', '#FF8080']): self._activity = parent self._colors = ['#FFFFFF'] self._colors.append(colors[0]) self._colors.append(colors[1]) self._colors.append('#000000') self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("draw", self.__draw_cb) self._canvas.connect("button-press-event", self._button_press_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - (GRID_CELL_SIZE * 1.5) self._scale = self._width / (20 * DOT_SIZE * 1.1) self._dot_size = int(DOT_SIZE * self._scale) self._space = int(self._dot_size / 5.) self.we_are_sharing = False self._sum = 0 self._mode = 'ten' self.custom = [1, 1, 1, 1, 10] # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) Sprite(self._sprites, 0, 0, self._box(self._width, self._height, color=colors[1])) self._number_box = Sprite(self._sprites, 0, 0, self._box( self._width, 2 * self._dot_size, color=colors[1])) self._number_box.set_label_attributes(48) self._dots = [] for p in range(SIX): y = self._height - self._space Sprite(self._sprites, 0, y, self._line(vertical=False)) x = int(p * self._width / 6) + self._space y -= self._dot_size for d in range(3): # bottom of fives row self._dots.append( Sprite(self._sprites, x, y, self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set # self._dots[-1].set_label_color('white') x += self._dot_size + self._space x = int((p * self._width / 6.) + self._dot_size / 2.) + self._space y -= self._dot_size + self._space for d in range(2): # top of fives row self._dots.append( Sprite(self._sprites, x, y, self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set # self._dots[-1].set_label_color('white') x += self._dot_size + self._space y -= self._dot_size Sprite(self._sprites, 0, y, self._line(vertical=False)) x = int((p * self._width / 6.) + self._dot_size / 2.) + self._space y -= self._dot_size for d in range(2): # bottom of threes row self._dots.append( Sprite(self._sprites, x, y, self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set # self._dots[-1].set_label_color('white') x += self._dot_size + self._space x = int((p * self._width / 6.) + self._dot_size) + self._space y -= self._dot_size + self._space for d in range(1): # top of threes row self._dots.append( Sprite(self._sprites, x, y, self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set # self._dots[-1].set_label_color('white') x += self._dot_size + self._space y -= self._dot_size Sprite(self._sprites, 0, y, self._line(vertical=False)) x = int((p * self._width / 6.) + self._dot_size / 2.) + self._space y -= self._dot_size for d in range(2): # twos row self._dots.append( Sprite(self._sprites, x, y, self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set # self._dots[-1].set_label_color('white') x += self._dot_size + self._space y -= self._dot_size Sprite(self._sprites, 0, y, self._line(vertical=False)) x = int((p * self._width / 6.) + self._dot_size) + self._space y -= self._dot_size for d in range(1): # ones row self._dots.append( Sprite(self._sprites, x, y, self._new_dot(self._colors[0]))) self._dots[-1].type = 0 # not set # self._dots[-1].set_label_color('white') x += self._dot_size + self._space y -= self._dot_size Sprite(self._sprites, 0, y, self._line(vertical=False)) for p in range(SIX - 1): x = int((p + 1) * self._width / 6) Sprite(self._sprites, x - 1, y, self._line(vertical=True)) # and initialize a few variables we'll need. self._all_clear()
class Game(): ''' OLPC XO man color changer designed in memory of Nat Jacobson ''' def __init__(self, canvas, parent=None, mycolors=['#A0FFA0', '#FF8080']): self._activity = parent self.colors = [mycolors[0]] self.colors.append(mycolors[1]) self._canvas = canvas if parent is not None: parent.show_all() self._parent = parent self._canvas.connect("draw", self.__draw_cb) self._canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self._canvas.connect("button-press-event", self._button_press_cb) self._canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK) self._canvas.connect('button-release-event', self._button_release_cb) self._canvas.add_events(Gdk.EventMask.POINTER_MOTION_MASK) self._canvas.connect("motion-notify-event", self._mouse_move_cb) self._width = Gdk.Screen.width() self._height = Gdk.Screen.height() - GRID_CELL_SIZE self._scale = self._width / 1200. self.press = None self.dragpos = [0, 0] self.startpos = [0, 0] self._dot_cache = {} self._xo_cache = {} self._radius = 22.5 self._stroke_width = 9.5 # Generate the sprites we'll need... self._sprites = Sprites(self._canvas) self._sprites.set_delay(True) self._dots = [] self._xo_man = None self._generate_bg('#FFF') # First dot, starting angle self._cxy = [self._width / 2, self._height / 2] self._xy = [self._width / 2 + 120 * self._scale, self._height / 2 - self._radius * self._scale] self._angle = 0 self._dot_size_plus = self._radius * 3 * self._scale self._min = -self._dot_size_plus / 3 self._max = self._height - (self._dot_size_plus / 2.2) self._zones = [] self._calc_zones() self._generate_spiral() self._sprites.draw_all() def _calc_zones(self): for color in colors: rgb1 = _from_hex(color[0]) rgb2 = _from_hex(color[1]) dv = _contrast(rgb1, rgb2) dh = _delta_hue(rgb1, rgb2) self._zones.append(_zone(dv, dh)) def _calc_next_dot_position(self): ''' calculate spiral coordinates ''' dx = self._xy[0] - self._cxy[0] dy = self._xy[1] - self._cxy[1] r = sqrt(dx * dx + dy * dy) c = 2 * r * pi a = atan2(dy, dx) da = (self._dot_size_plus / c) * 2 * pi a += da r += self._dot_size_plus / (c / self._dot_size_plus) self._xy[0] = r * cos(a) + self._cxy[0] self._xy[1] = r * sin(a) + self._cxy[1] if self._xy[1] < self._min or self._xy[1] > self._max: self._calc_next_dot_position() def _generate_spiral(self): ''' Make a new set of dots for a sprial ''' for z in range(4): for i in range(len(colors)): if self._zones[i] == z: self._dots.append( Sprite(self._sprites, self._xy[0], self._xy[1], self._new_dot(colors[i]))) self._dots[-1].type = i self._calc_next_dot_position() if self._xo_man is None: x = 510 * self._scale y = 280 * self._scale self._xo_man = Sprite(self._sprites, x, y, self._new_xo_man(self.colors)) self._xo_man.type = None def move_dot(self, i, x, y): self._dots[i].move((x, y)) def get_dot_xy(self, i): return self._dots[i].get_xy() def move_xo_man(self, x, y): self._xo_man.move((x, y)) def get_xo_man_xy(self): return self._xo_man.get_xy() def rotate(self): x, y = self._dots[0].get_xy() for i in range(len(colors) - 1): self._dots[i].move(self._dots[i + 1].get_xy()) self._dots[-1].move((x, y)) def _generate_bg(self, color): ''' a background color ''' self._bg = Sprite(self._sprites, 0, 0, self._new_background(color)) self._bg.set_layer(0) self._bg.type = None def adj_background(self, color): ''' Change background ''' self._bg.set_image(self._new_background(color)) self._bg.set_layer(0) def _button_press_cb(self, win, event): win.grab_focus() x, y = map(int, event.get_coords()) self.dragpos = [x, y] spr = self._sprites.find_sprite((x, y)) if spr == None or spr == self._bg: return self.startpos = spr.get_xy() self.press = spr def _mouse_move_cb(self, win, event): """ Drag a rule with the mouse. """ if self.press is None: self.dragpos = [0, 0] return True win.grab_focus() x, y = map(int, event.get_coords()) dx = x - self.dragpos[0] dy = y - self.dragpos[1] self.press.move_relative((dx, dy)) self.dragpos = [x, y] def _button_release_cb(self, win, event): if self.press == None: return True if _distance(self.press.get_xy(), self.startpos) < 20: if type(self.press.type) == int: self.i = self.press.type self._new_surface() self.press.move(self.startpos) self.press = None def _new_surface(self): self.colors[0] = colors[self.i][0] self.colors[1] = colors[self.i][1] self._xo_man.set_image(self._new_xo_man(colors[self.i])) self._xo_man.set_layer(100) def __draw_cb(self, canvas, cr): self._sprites.redraw_sprites(cr=cr) def do_expose_event(self, event): ''' Handle the expose-event by drawing ''' # Restrict Cairo to the exposed area cr = self._canvas.window.cairo_create() cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() # Refresh sprite list self._sprites.redraw_sprites(cr=cr) def _destroy_cb(self, win, event): Gtk.main_quit() def _new_dot(self, color): ''' generate a dot of a color color ''' if True: # not color in self._dot_cache: self._stroke = color[0] self._fill = color[1] self._svg_width = int(60 * self._scale) self._svg_height = int(60 * self._scale) pixbuf = svg_str_to_pixbuf( self._header() + \ '<circle cx="%f" cy="%f" r="%f" stroke="%s" fill="%s" \ stroke-width="%f" visibility="visible" />' % ( 30 * self._scale, 30 * self._scale, self._radius * self._scale, self._stroke, self._fill, self._stroke_width * self._scale) + \ self._footer()) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self._svg_width, self._svg_height) context = cairo.Context(surface) Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0) context.rectangle(0, 0, self._svg_width, self._svg_height) context.fill() # self._dot_cache[color] = surface return surface # self._dot_cache[color] def _new_background(self, color): ''' Background color ''' self._svg_width = int(self._width) self._svg_height = int(self._height) string = \ self._header() + \ '<rect width="%f" height="%f" x="%f" \ y="%f" fill="%s" stroke="none" visibility="visible" />' % ( self._width, self._height, 0, 0, color) + \ self._footer() pixbuf = svg_str_to_pixbuf(string) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self._svg_width, self._svg_height) context = cairo.Context(surface) Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0) context.rectangle(0, 0, self._svg_width, self._svg_height) context.fill() return surface def _new_xo_man(self, color): ''' generate a xo-man of a color color ''' if True: # not color in self._xo_cache: self._stroke = color[0] self._fill = color[1] self._svg_width = int(240. * self._scale) self._svg_height = int(260. * self._scale) string = \ self._header() + \ '<g>' + \ '<g id="XO">' + \ '<path id="Line1" d="M%f,%f C%f,%f %f,%f %f,%f" stroke="%s" \ stroke-width="%f" stroke-linecap="round" fill="none" visibility="visible" />' \ % ( 165.5 * self._scale, 97 * self._scale, 120 * self._scale, 140.5 * self._scale, 120 * self._scale, 140.5 * self._scale, 74.5 * self._scale, 188 * self._scale, self._stroke, 37 * self._scale) + \ '<path id="Line2" d="M%f,%f C%f,%f %f,%f %f,%f" stroke="%s" \ stroke-width="%f" stroke-linecap="round" fill="none" visibility="visible" />' \ % ( 165.5 * self._scale, 188 * self._scale, 120 * self._scale, 140.5 * self._scale, 120 * self._scale, 140.5 * self._scale, 74.5 * self._scale, 97 * self._scale, self._stroke, 37 * self._scale) + \ '<path id="Fill1" d="M%f,%f C%f,%f %f,%f %f,%f" stroke="%s" \ stroke-width="%f" stroke-linecap="round" fill="none" visibility="visible" />' \ % ( 165.5 * self._scale, 97 * self._scale, 120 * self._scale, 140.5 * self._scale, 120 * self._scale, 140.5 * self._scale, 74.5 * self._scale, 188 * self._scale, self._fill, 17 * self._scale) + \ '<path id="Fill2" d="M%f,%f C%f,%f %f,%f %f,%f" stroke="%s" \ stroke-width="%f" stroke-linecap="round" fill="none" visibility="visible" />' \ % ( 165.5 * self._scale, 188 * self._scale, 120 * self._scale, 140.5 * self._scale, 120 * self._scale, 140.5 * self._scale, 74.5 * self._scale, 97 * self._scale, self._fill, 17 * self._scale) + \ '<circle id="Circle" cx="%f" cy="%f" r="%f" \ fill="%s" stroke="%s" stroke-width="%f" visibility="visible" />' % ( 120 * self._scale, 61.5 * self._scale, 27.5 * self._scale, self._fill, self._stroke, 11 * self._scale) + \ '</g></g>' + \ self._footer() pixbuf = svg_str_to_pixbuf(string) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self._svg_width, self._svg_height) context = cairo.Context(surface) Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0) context.rectangle(0, 0, self._svg_width, self._svg_height) context.fill() # self._xo_cache[color] = surface return surface # self._xo_cache[color] def _header(self): return '<svg\n' + 'xmlns:svg="http:#www.w3.org/2000/svg"\n' + \ 'xmlns="http://www.w3.org/2000/svg"\n' + \ 'xmlns:xlink="http://www.w3.org/1999/xlink"\n' + \ 'version="1.1"\n' + 'width="' + str(self._svg_width) + '"\n' + \ 'height="' + str(self._svg_height) + '">\n' def _footer(self): return '</svg>\n'