class FloatButtonWidget(ButtonBehavior, AnchorLayout): __shape_up__ = None __shape_down__ = None def collide_point(self, x, y): return (x > self.x and x < self.x + self.width) and (y > self.y and y < self.y + self.height) def on_press(self): if self.__shape_down__ == None: self.__shape_down__ = InstructionGroup(grup="__shape_down__") else: self.canvas.remove(self.__shape_down__) self.__shape_down__.clear() color = Color(0, 0, 0, .4) self.__shape_down__.add(color) self.__shape_down__.add(Ellipse(pos=self.pos, size=self.size)) self.canvas.add(self.__shape_down__) super(FloatButtonWidget, self).on_press() def on_release(self): self.canvas.remove(self.__shape_down__) self.__shape_down__.clear() super(FloatButtonWidget, self).on_release()
class HeaderLabel(Label): def __init__(self, **kwargs): self.instr = InstructionGroup() self.bgColor_255 = (60,60,60,255) #BG color in the 0 to 255 scale #Using map to produce a tuple scale 0 to 1 from a tuple scaled 0 to 255 self.bgColor_1 = tuple(list(map(lambda x: round(x/255, 3), self.bgColor_255))) super(HeaderLabel, self).__init__(**kwargs) # Customizing the visuals self.canvas.before.add(self.instr) self.color = (1, 1, 1, 1) #Font color in the 0 to 1 scale self.bold = True self.font_size = 20 def on_pos(self, *args): self.evaluateColor() def on_size(self, *args): self.evaluateColor() def evaluateColor(self): self.instr.clear() self.instr.add(Color(*self.bgColor_1)) #BG self.instr.add(Rectangle(pos=self.pos, size=self.size))
class LoopBars(object): def __init__(self, width, height, canvas): self.width = width self.height = height self.start = 0 self.canvas = canvas self.loop = False self.loops = InstructionGroup() def loop_func(self, loop): if loop: loopL = Line(points=[30+20,self.height,30+20,0]) loopR = Line(points=[30+70,self.height,30+70,0]) handle_size=(20,20) top_padding = 20 loopHandleL = Rectangle(pos=(loopL.points[0]-(handle_size[0]/2),self.height-top_padding), size=handle_size) loopHandleR = Rectangle(pos=(loopR.points[0]-(handle_size[0]/2),self.height-top_padding), size=handle_size) self.loops.add(Color(0,1,1)) self.loops.add(loopL) self.loops.add(Color(1,0,1)) self.loops.add(loopR) self.loops.add(loopHandleL) self.loops.add(loopHandleR) self.canvas.add(self.loops) else: self.canvas.remove(self.loops) self.loops.clear() def drag_loop_bar(self, loop): # only move loop line if dragged by handle pass
class String(Widget): string_tuning = ObjectProperty(None) def __init__(self, active_fret=None, *args, **kwargs): super().__init__(**kwargs) self.active_fret = active_fret self.active_rect = InstructionGroup() self.bind(size=self._update_canvas, pos=self._update_canvas) def _update_canvas(self, instance, value): self._update_note(instance, value) def _update_note(self, instance, value): self.active_rect.clear() if self.active_fret is None: return left, right = self.parent.fret_ranges[self.active_fret] width = right - left x_pos = left self.active_rect.add(Color(1, 1, 1, 0.2)) self.active_rect.add( Rectangle(size=[width, self.height], pos=[x_pos, self.y])) self.canvas.add(self.active_rect) def _clear_note(self): self.active_rect.clear() def _play_note(self, fret_num): self.active_fret = fret_num self._update_note(None, None)
class LabelClicableBase(ButtonBehavior, LabelBase): tag = ObjectProperty(None, allowNone=True) def __init__(self, **kargs): super(LabelClicableBase, self).__init__(**kargs) self.shape_down = None def collide_point(self, x, y): return (x > self.x and x < self.x + self.width) and (y > self.y and y < self.y + self.height) def on_touch_down(self, touch, *args): if self.collide_point(touch.x, touch.y): size = ceil(self.height * 0.7), ceil(self.height * 0.7) w, h = size pos = touch.x - w / 2, touch.y - h / 2 if self.shape_down == None: self.shape_down = InstructionGroup(group="shape_down") else: self.container.canvas.before.remove(self.shape_down) self.shape_down.clear() color = Color(0, 0, 0, .4) self.shape_down.add(color) self.shape_down.add(Ellipse(pos=pos, size=size)) self.container.canvas.before.add(self.shape_down) Clock.schedule_once(self.remove_shape_down, .05) super(LabelClicableBase, self).on_touch_down(touch) return True def remove_shape_down(self, dt): self.container.canvas.before.remove(self.shape_down) self.shape_down.clear()
class AltLabel(BoxLayout): """ """ active = BooleanProperty(False) def __init__(self, **kwargs): super(AltLabel, self).__init__(**kwargs) self.onColor = (1, 0, 0, 1) self.offColor = (0, 1, 0, 1) self.bold = False self.font_size = 14 self.instr = InstructionGroup() self.canvas.before.add(self.instr) def on_active(self, *args): self.evaluateColor() def evaluateColor(self): print("Evaluating") if self.active: self.colorTuple = self.onColor else: self.colorTuple = self.offColor self.instr.clear() self.instr.add(Color(*self.colorTuple)) self.instr.add(Rectangle(pos=self.pos, size=self.size)) def on_size(self, *args): self.evaluateColor()
class PrTracks: """ PrTracks ======== provides object which manage track instruction groups 1. Container instruction group for canvas 2. List of PrTracks 3. show/hide tracks 4. z-order handling """ def __init__(self): self.container = InstructionGroup() self.tracks = {} def get(self, idx): if idx in self.tracks: return self.tracks[idx] def add(self, idx, track): self.tracks[idx] = track self.container.add(track.canvas) def remove(self, idx): self.container.remove(self.tracks[idx].canvas) self.tracks[idx] = None def show(self, idx): track = self.tracks[idx] if track: if self.tracks[idx].visible == False: # self.container.add(track.canvas) # track.visible = True track.show() def hide(self, idx): track = self.tracks[idx] if track: if self.tracks[idx].visible: # self.container.remove(track.canvas) # track.visible = False track.hide() def draw(self): self.container.clear() for key in self.tracks: self.container.add(self.tracks[key].canvas) return self.container
class ScrollBox(ScrollView): """A ScrollView object which contains a box widget inside Ensures scrolling on a white background Remove the on_size method to prevent the background color from being implemented""" def __init__(self, **kwargs): super(ScrollBox, self).__init__(**kwargs) self.bgColor_1 = (1, 1, 1, 1) #White self.instr = InstructionGroup() self.canvas.before.add(self.instr) def on_size(self, *args): self.instr.clear() self.instr.add(Color(*self.bgColor_1)) self.instr.add(Rectangle(pos=self.pos, size=self.size))
class AltLabel(Label): """ """ active = BooleanProperty(False) def __init__(self, **kwargs): self.instr = InstructionGroup() self.offColor = (1, 1, 1, 1) self.onColor = (0.8, 0.8, 0.8, 1) super(AltLabel, self).__init__(**kwargs) self.bold = False self.font_size = 18 self.halign="left" self.valign="middle" self.bind(size=self.setter('text_size')) self.size_hint=(1.0, None) self.color = (0, 0, 0, 1) self.canvas.before.add(self.instr) def on_active(self, *args): self.evaluateColor() def evaluateColor(self): if self.active: self.colorTuple = self.onColor else: self.colorTuple = self.offColor self.instr.clear() self.instr.add(Color(*self.colorTuple)) self.instr.add(Rectangle(pos=self.pos, size=self.size)) def on_size(self, *args): self.evaluateColor() def on_pos(self, *args): self.evaluateColor()
class FloatButton(ButtonBehavior, Widget): bgColor = StringProperty("#108710") icon = StringProperty(res.FA_EDIT) font_size = StringProperty("30dp") color = ListProperty([1, 1, 1, 1]) def __init__(self, *args, **kwargs): super(FloatButton, self).__init__(*args, **kwargs) self.shape_up = None self.shape_down = None def on_color(self, w, val): if "#" in val: val = "".join(val) self.color = get_color_from_hex(val) def on_bgColor(self, root, val): if self.shape_up == None: self.shape_up = InstructionGroup(grup="shape_up") else: self.shape.canvas.remove(self.shape_up) self.shape_up.clear() color = Color() color.rgb = get_color_from_hex(val) self.shape_up.add(color) self.shape_up.add(Ellipse(pos=self.shape.pos, size=self.shape.size)) self.shape.canvas.before.add(self.shape_up) self.shape_up.clear() def collide_point(self, x, y): return Vector(x, y).distance(self.center) <= self.width / 2 def on_touch_down(self, touch, *args): super(FloatButton, self).on_touch_down(touch) if self.collide_point(touch.x, touch.y): if self.shape_down == None: self.shape_down = InstructionGroup(grup="shape_down") else: self.shape.canvas.before.remove(self.shape_down) self.shape_down.clear() color = Color(0, 0, 0, .4) self.shape_down.add(color) self.shape_down.add( Ellipse(pos=self.shape.pos, size=self.shape.size)) self.shape.canvas.before.add(self.shape_down) Clock.schedule_once(self.remove_shape_down, .05) return True def remove_shape_down(self, dt): self.shape.canvas.before.remove(self.shape_down) self.shape_down.clear()
class CustomCarousel(Carousel): def __init__(self, **kwargs): super(CustomCarousel, self).__init__(**kwargs) self.background_instruction = InstructionGroup() self.bind(size=self.adjust_background) def setup_background(self): self.parent.canvas.before.add(self.background_instruction) def on_index(self, *args): super(CustomCarousel, self).on_index(*args) current_tab = str(self.slides.index(self.current_slide)) self.set_tab_states_to_normal() self.set_tab_down(current_tab) self.adjust_background() App.get_running_app().root.commands_stack.append(self.current_slide) def set_tab_down(self, current_tab): try: tab = list( filter(lambda a: a.id == current_tab, self.parent.action_buttons))[0] tab.state = 'down' except IndexError: pass def set_tab_states_to_normal(self): for tab in self.parent.action_buttons: tab.state = 'normal' def adjust_background(self, *args, **kwargs): with ignored(Exception): self.background_instruction.clear() self.background_instruction.add( Rectangle(pos=self.pos, size=Window.size, source=self.parent.get_proper_background_image()))
class ColorAwareLabel(Label): """Uses the default KeyToColor Object and thus the default ColorColleciton object to automatically assign itself a background color depending on its text When the text is updated, so is the background color depending on how KeyToColor is configured Important Note: Do not pass text as keyword as the method to evaluate color uses properties that are defined after super is run, when super runs the evaluateColor method, they will be missing """ def __init__(self, **kwargs): self.instr = InstructionGroup() self.colorRef = KeyToColor() super(ColorAwareLabel, self).__init__(**kwargs) self.bold = False self.font_size = 18 self.colorTuple = self.colorRef.getColor(self.text) self.canvas.before.add(self.instr) def evaluateColor(self): self.colorTuple = self.colorRef.getColor(self.text) self.instr.clear() self.instr.add(Color(*self.colorTuple)) self.instr.add(Rectangle(pos=self.pos, size=self.size)) def on_text(self, *args): self.evaluateColor() def on_size(self, *args): self.evaluateColor()
class StringWithTuner(Widget): string_tuning = ObjectProperty(None) def __init__(self, active_fret=None, *args, **kwargs): super().__init__(**kwargs) self.active_fret = active_fret self.active_rect = InstructionGroup() self.colored_frets = InstructionGroup() self.bind(size=self._update_canvas, pos=self._update_canvas) def _update_canvas(self, instance, value): self._update_note(instance, value) self._update_colored_frets() def _update_note(self, instance, value): self.active_rect.clear() if self.active_fret is None: return left, right = self.parent.fret_ranges[self.active_fret] width = right - left x_pos = left self.active_rect.add(Color(1, 1, 1, 0.2)) self.active_rect.add( Rectangle(size=[width, self.height], pos=[x_pos, self.y])) self.canvas.add(self.active_rect) def _update_colored_frets(self): color_map = self.parent.color_map self.colored_frets.clear() note_idx = chrom_scale.index(self.string_tuning.text) i = 0 while i < 25: note = chrom_scale[(note_idx + i) % 12] if note in color_map: left, right = self.parent.fret_ranges[i] width = right - left self.colored_frets.add(Color(*color_map[note])) self.colored_frets.add( Rectangle(size=[width, self.height], pos=[left, self.y])) i += 1 self.canvas.add(self.colored_frets) def _clear_note(self): self.active_rect.clear() def _play_note(self, fret_num): self.active_fret = fret_num self._update_note(None, None)
class RealtimeTouchMove(State): def __init__(self, target, cells, **kwargs): super(RealtimeTouchMove, self).__init__(target, **kwargs) self.cells = cells self.moving = False self.instructions = InstructionGroup() self.highlight_tiles(cells) self.foreshadowed = self.target._current_cell self.velocity = [0, 0] self.target.anim_delay = .2 self.movement_axis = 0 def touch(self, touch, *args): pos = self.target.map.pixel_from_screen(*touch.pos) cell = self.target.map.layers.by_name['below'].get_at(*pos) origin_cell = self.target.map.layers.by_name['below'].get_at( *self.target.pos) if cell is not None and cell.tile.is_passable(): cells = cell.layer.a_star_search(origin_cell, cell) # if there's only two cells selected, and goal is not origin neighbor... then run away, RUN AWAY! if len(cells) == 2 and cell not in self.target.map.layers.by_name[ 'below'].get_neighbor_cells(origin_cell): return if len(cells) > 1: cells.reverse() self.instructions.clear() self.instructions = InstructionGroup() self.highlight_tiles(cells) self.cells = cells self.moving = False def update(self, dt): if not self.moving: self.check_moving() else: self.move(dt) def move(self, dt): delta_x = self.target.x - self.foreshadowed.px delta_y = self.target.y - self.foreshadowed.py distance = Vector(*self.target.pos).distance( (self.foreshadowed.px, self.foreshadowed.py)) if distance >= 1.0: delta_x = (delta_x / distance) * (dt * 50) delta_y = (delta_y / distance) * (dt * 50) x, y = self.target.pos x += -delta_x y += -delta_y self.target.set_position(x, y) distance = Vector(*self.target.pos).distance( (self.foreshadowed.px, self.foreshadowed.py)) if distance <= 1.0: self.check_moving() def done_moving(self, *args): self.target.set_position(self.foreshadowed.px, self.foreshadowed.py) self.moving = False def highlight_tiles(self, tiles): self.instructions.clear() for tile in tiles: self.instructions.add(Color(rgba=[.3, 1, .3, .3])) self.instructions.add( Rectangle(pos=(tile.px, tile.py), size=(tile.px_width, tile.px_height))) self.target.game.layer_widgets['below'].canvas.add(self.instructions) def check_moving(self, *args): last_axis = self.movement_axis last_cell = self.foreshadowed if self.cells: self.moving = True self.foreshadowed = self.cells.pop() print('moving to', self.foreshadowed.bottomleft) if self.foreshadowed.px != last_cell.px: self.movement_axis = 0 if self.foreshadowed.px < last_cell.px: self.target.set_face('left') self.velocity = [self.target.map.tile_width * -1, 0] else: self.target.set_face('right') self.velocity = [self.target.map.tile_width, 0] elif self.foreshadowed.py != last_cell.py: self.movement_axis = 1 if self.foreshadowed.py < last_cell.py: self.target.set_face('down') self.velocity = [0, self.target.map.tile_width * -1] else: self.target.set_face('up') self.velocity = [0, self.target.map.tile_width] if last_axis != self.movement_axis: print('axis changed!') print(self.target.pos) self.target.set_position(last_cell.px, last_cell.py) print(self.target.pos) print(last_cell.bottomleft, self.foreshadowed.bottomleft) else: self.done_moving() self.end() print('no cells') return self.target.activate_object(target='floor', button_press=False) def end(self): self.target.state = IdleReadyState(self.target) self.instructions.clear()
class Fretboard(BoxLayout): song = ObjectProperty(None) def __init__(self, *args, **kwargs): super().__init__(**kwargs) self.fret_bars = InstructionGroup() self.inlays = InstructionGroup() self.beat_num = 0 self.background = Rectangle(size=self.size, pos=self.pos) self.bind(size=self._update_canvas, pos=self._update_canvas) def _update_canvas(self, instance, value): # instance is self, value is bound value that changed (size or pos). self._update_background() self._update_fret_bars() self._update_fret_ranges() self._update_inlays() def _update_background(self): self.background.pos = self.pos self.background.size = self.size def _update_fret_bars(self): temperament = 2**( 1 / 12 ) # Ratio of fret[i]/fret[i+1] for 12-tone equal temperament. self.fret_bar_width = self.width * ( 0.1 / 24.75) # Gibson ratio of fret bar width to scale length. # All fret_pos in fret_positions is in interval [0, 1). fret_positions = [ 1 - (1 / (temperament**fret_num)) for fret_num in range(25) ] # Move fret_position[0] up to make a box for the nut, scale fret_position[i] accordingly. nut_width_ratio = 0.03 # Percentage of nut_width vs fretboard.width. nut_offsets = [fret_pos + (1/temperament**fret_num)*nut_width_ratio \ for fret_num, fret_pos in enumerate(fret_positions)] offset_fret_positions = [ fret_pos + offset for fret_pos, offset in zip(fret_positions, nut_offsets) ] # Stretch all fret_positions so they fit the entire width of the fretboard. stretched_fret_positions = [ fret_pos / offset_fret_positions[-1] for fret_pos in offset_fret_positions ] # Calculate actual fret_positions. actual_fret_positions = [ fret_pos * self.width + self.x for fret_pos in stretched_fret_positions ] self.fret_bars.clear() self.fret_bars.add(Color(0, 0, 0, 1)) for fret_pos in actual_fret_positions: self.fret_bars.add( Rectangle(size=[self.fret_bar_width, self.height], pos=[fret_pos, self.y])) self.canvas.add(self.fret_bars) self.fret_bar_positions = actual_fret_positions def _update_fret_ranges(self): start = self.x fret_ranges = [] for fret_pos in self.fret_bar_positions: fret_ranges.append((start, fret_pos)) start = (fret_pos + self.fret_bar_width) self.fret_ranges = fret_ranges def _update_inlays(self): self.inlays.clear() self.inlays.add(Color(1, 1, 1, 1)) d = self.height * 0.15 for i, fret_range in enumerate(self.fret_ranges): # Single circular inlay. if i in range(3, 10, 2) or i in range(15, 25, 2): x_pos = (sum(fret_range) / 2) y_pos = (self.height / 2) + self.y self.inlays.add( Ellipse(size=[d, d], pos=[x_pos - d / 2, y_pos - d / 2])) # Double circular inlay at fret 12. elif i == 12: x_pos = (sum(fret_range) / 2) y_pos1 = (self.height / 3) + self.y y_pos2 = 2 * (self.height / 3) + self.y self.inlays.add( Ellipse(size=[d, d], pos=[x_pos - d / 2, y_pos1 - d / 2])) self.inlays.add( Ellipse(size=[d, d], pos=[x_pos - d / 2, y_pos2 - d / 2])) self.canvas.add(self.inlays) def _update_key_sig_colored_frets(self, key_sig): from itertools import compress from collections import deque note, mode = key_sig.split() # Representative of W-W-H-W-W-W-H (the major scale). interval_sequence = deque([1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1]) roygbiv = [ 'red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet' ] modes = { 'Major': 0, 'Dorian': 2, 'Phrygian': 4, 'Lydian': 5, 'Mixolydian': 7, 'Minor': 9, 'Locrian': 11 } chrom_scale = 'C C#/Db D D#/Eb E F F#/Gb G G#/Ab A A#/Bb B'.split() mode_pattern = interval_sequence.copy() mode_pattern.rotate(-1 * modes[mode]) note_pattern = chrom_scale.copy() while note != note_pattern[0]: note_pattern.rotate(-1) notes_in_key = list(compress(note_pattern, mode_pattern)) color_map = {note: color for note, color in zip(notes_in_key, roygbiv)} def _clear_frets(self): for i in range(1, 7): self.ids[str(i)]._play_note(None) def play_notes(self): for string in range(1, 7): fret_num = random.randrange(25) self.ids[str(string)].play_note(fret_num) def play_song(self): track1 = self.song.song[0] self.track = track1 self.start1 = time.time() self.start2 = timeit.default_timer() # spt_play_song(self.song) self._play_song() def restart_song(self): # spt_restart() self._play_song() def _play_song(self, seconds=None): # Clock will pass beat.seconds as an argument, it is not needed. beat = self.track[self.beat_num] Clock.schedule_once(self._play_song, beat.seconds) self._play_beat(beat.frets) self.beat_num += 1 if self.beat_num == len(self.track): end1 = time.time() end2 = timeit.default_timer() print("Total Time (time): ", end1 - self.start1) print("Total Time (timeit): ", end2 - self.start2) self._clear_frets() return def _play_beat(self, frets): for i, fret_num in enumerate(frets, 1): self.ids[str(i)]._play_note(fret_num)
class FretboardWithTuner(BoxLayout): song = ObjectProperty(None) def __init__(self, *args, **kwargs): super().__init__(**kwargs) self.fret_bars = InstructionGroup() self.inlays = InstructionGroup() self.beat_num = 0 self.color_map = {} self.bind(size=self._update_canvas, pos=self._update_canvas) Clock.schedule_once(self._tune_to_standard, 0) # cannot use kv id's until __init__ is done. def _tune_to_standard(self, dt): for id, tuning in zip([6, 5, 4, 3, 2, 1], "EADGBE"): self.ids[str(id)].string_tuning.text = tuning def _update_canvas(self, instance, value): # instance is self, value is bound value that changed (size or pos). self._update_fret_bars() self._update_fret_ranges() self._update_inlays() def _update_fret_bars(self): temperament = 2**( 1 / 12 ) # Ratio of fret[i]/fret[i+1] for 12-tone equal temperament. self.fret_bar_width = self.width * ( 0.1 / 24.75) # Gibson ratio of fret bar width to scale length. # All fret_pos in fret_positions is in interval [0, 1). fret_positions = [ 1 - (1 / (temperament**fret_num)) for fret_num in range(25) ] # Move fret_position[0] up to make a box for the nut, scale fret_position[i] accordingly. nut_width_ratio = 0.03 # Percentage of nut_width vs fretboard.width. offsets = [fret_pos + (1/temperament**fret_num)*nut_width_ratio \ for fret_num, fret_pos in enumerate(fret_positions)] offset_fret_positions = [ fret_pos + offset for fret_pos, offset in zip(fret_positions, offsets) ] # Stretch all fret_positions so they fit the entire width of the fretboard. stretched_fret_positions = [ fret_pos / offset_fret_positions[-1] for fret_pos in offset_fret_positions ] # Calculate actual fret_positions. actual_fret_positions = [ fret_pos * self.width + self.x for fret_pos in stretched_fret_positions ] self.fret_bars.clear() self.fret_bars.add(Color(0, 0, 0, 1)) for fret_pos in actual_fret_positions: self.fret_bars.add( Rectangle(size=[self.fret_bar_width, self.height], pos=[fret_pos, self.y])) self.canvas.add(self.fret_bars) self.fret_bar_positions = actual_fret_positions def _update_fret_ranges(self): start = self.x fret_ranges = [] for fret_pos in self.fret_bar_positions: fret_ranges.append((start, fret_pos)) start = (fret_pos + self.fret_bar_width) self.fret_ranges = fret_ranges def _update_inlays(self): self.inlays.clear() self.inlays.add(Color(1, 1, 1, 1)) d = self.height * 0.15 for i, fret_range in enumerate(self.fret_ranges): # Single circular inlay. if i in range(3, 10, 2) or i in range(15, 25, 2): x_pos = (sum(fret_range) / 2) y_pos = (self.height / 2) + self.y self.inlays.add( Ellipse(size=[d, d], pos=[x_pos - d / 2, y_pos - d / 2])) # Double circular inlay at fret 12. elif i == 12: x_pos = (sum(fret_range) / 2) y_pos1 = (self.height / 3) + self.y y_pos2 = 2 * (self.height / 3) + self.y self.inlays.add( Ellipse(size=[d, d], pos=[x_pos - d / 2, y_pos1 - d / 2])) self.inlays.add( Ellipse(size=[d, d], pos=[x_pos - d / 2, y_pos2 - d / 2])) self.canvas.add(self.inlays) def _update_key_sig_colored_frets(self, key_sig): from itertools import compress from collections import deque note, mode = key_sig.split() roygbiv = [ [1, 0.102, 0.102, 1], # red [1, 0.549, 0.102, 1], # orange [1, 1, 0.102, 1], # yellow [0.102, 1, 0.102, 1], # green [0.102, 0.102, 1, 1], # blue [0.549, 0.102, 1, 1], # indigo [1, 0, 0.502, 1] ] # violet' modes = { 'Major': 0, 'Dorian': 2, 'Phrygian': 4, 'Lydian': 5, 'Mixolydian': 7, 'Minor': 9, 'Locrian': 11 } # Representative of W-W-H-W-W-W-H (the major scale). mode_pattern = deque([1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1]) note_pattern = deque(chrom_scale[:]) mode_pattern.rotate(-1 * modes[mode]) while note != note_pattern[0]: note_pattern.rotate(-1) notes_in_key = list(compress(note_pattern, mode_pattern)) self.color_map = { note: color for note, color in zip(notes_in_key, roygbiv) } for child in self.children: child._update_colored_frets() def _clear_frets(self): for i in range(1, 7): self.ids[str(i)]._play_note(None)
class MasterWin(Widget): Builder.load_file('master.kv') Window.size = (640, 480) def __init__(self, master, **kwargs): super().__init__(**kwargs) self.master = master self.rects = InstructionGroup() self.ids.mask.canvas.add(self.rects) Window.bind(on_joy_axis=self.on_joy_axis) Window.bind(on_joy_button_down=self.on_joy_button_down) Window.bind(on_joy_button_up=self.on_joy_button_up) @mainthread def update_img(self, width, height, img): texture = Texture.create(size=(width, height)) texture.blit_buffer(img.tobytes()) texture.flip_vertical() texture.flip_horizontal() self.ids.img.texture = texture @mainthread def update_rects(self, width, height, rects): self.rects.clear() # since the img may be scaled # need to scale the mask as well size = self.ids.img.size self.ids.mask.x_scale = size[0] // width self.ids.mask.y_scale = size[1] // height for each in rects: # due to the img is flipped # the mask need to be flipped too left = size[0] - each[0] top = size[1] - each[1] temp = (left, top, -each[2], -each[3]) # noinspection PyArgumentList rect = Line(rectangle=temp) self.rects.add(rect) def on_joy_axis(self, _win, _stick_id, axis_id, val): if axis_id in (0, 1, 3, 4): act = {0: 'mov', 1: 'mov', 3: 'obs', 4: 'obs'}[axis_id] det = {0: 'down', 1: 'right', 3: 'down', 4: 'right'}[axis_id] self.handle_body(act, det, val) def on_joy_button_down(self, _win, _stick_id, btn_id): if btn_id == 1: self.master.ear.enable = True elif btn_id == 2: now = datetime.now().strftime('%Y-%m-%d %H-%M-%S') self.ids.img.export_to_png('{0}.png'.format(now)) elif btn_id == 3: self.handle_body('mov', 'down', 0) self.handle_body('mov', 'right', 0) self.handle_body('obs', 'down', 0) self.handle_body('obs', 'right', 0) def on_joy_button_up(self, _win, _stick_id, btn_id): if btn_id == 1: self.master.ear.enable = False def handle_body(self, act, det, val): data = ujson.dumps((act, det, val)) self.master.body_node.send_data(data)
class Maze(RelativeLayout): def __init__(self, **kwargs): global current_wedge super(RelativeLayout, self).__init__(**kwargs) self.wedge_list = [] self.color_list = [BLACK, BLACK, BLACK] self.ring_count = int(500 / CORRIDOR) self.inner_ring = 500 - (self.ring_count * CORRIDOR) if self.inner_ring < CORRIDOR: self.inner_ring = self.inner_ring + CORRIDOR self.ring_count -= 1 wedge_density = int(((2 * PI) * self.inner_ring) // CORRIDOR) for rnum in range(self.ring_count): wedge_count = Counter(rnum, wedge_density, self.inner_ring) wedge_size = (2 * PI) / wedge_count first = len(self.wedge_list) for wnum in range(wedge_count): a_left = wedge_size * wnum a_right = wedge_size * (wnum + 1) w = Wedge(a_left, a_right, (rnum, first), (wedge_count, self.ring_count, wedge_density), len(self.wedge_list), self.inner_ring) self.wedge_list.append(w) if rnum == self.ring_count - 1: self.outer_line = InstructionGroup() self.outer_size = wedge_size self.outer_count = wedge_count for wnum in range(len(self.wedge_list)): self.wedge_list[wnum].neighborize(self.wedge_list) self.wedge_list[current_wedge].makeactive(None) self.draw() def update(self): global current_wedge self.wedge_list[current_wedge].makecheck() self.canvas.clear() self.draw() self.canvas.ask_update() def setvalues(self): for wnum in range(len(self.wedge_list)): self.wedge_list[wnum].setcorners() def draw(self): with self.canvas: Color(*BLACK) self.drawouterring(self.outer_count, self.outer_size) for wnum in range(len(self.wedge_list)): with self.canvas: Color(*BLACK) self.wedge_list[wnum].draw(self.canvas) Color(*GREEN) self.wedge_list[wnum].draw_dot(self.canvas) def drawouterring(self, wedge_count, wedge_size): self.line = Line(circle=(CenterX, CenterY, self.inner_ring + (self.ring_count * CORRIDOR), 0, 360), width=WALL) self.outer_line.clear() for w_num in range(wedge_count): angle = w_num * wedge_size outer_corner = wedge_size / CORNERSIZE self.outer_line.add( Line(circle=(CenterX, CenterY, self.inner_ring + (self.ring_count * CORRIDOR), degrees(angle - outer_corner), degrees(angle + outer_corner)), width=CORNER, cap='round')) self.canvas.add(self.outer_line)
class RealtimeTouchMove(State): def __init__(self, target, cells, **kwargs): super(RealtimeTouchMove, self).__init__(target, **kwargs) self.cells = cells self.moving = False self.instructions = InstructionGroup() self.highlight_tiles(cells) self.foreshadowed = self.target._current_cell self.velocity = [0, 0] self.target.anim_delay = .2 self.movement_axis = 0 def touch(self, touch, *args): pos = self.target.map.pixel_from_screen(*touch.pos) cell = self.target.map.layers.by_name['below'].get_at(*pos) origin_cell = self.target.map.layers.by_name['below'].get_at(*self.target.pos) if cell is not None and cell.tile.is_passable(): cells = cell.layer.a_star_search(origin_cell, cell) # if there's only two cells selected, and goal is not origin neighbor... then run away, RUN AWAY! if len(cells) == 2 and cell not in self.target.map.layers.by_name['below'].get_neighbor_cells(origin_cell): return if len(cells) > 1: cells.reverse() self.instructions.clear() self.instructions = InstructionGroup() self.highlight_tiles(cells) self.cells = cells self.moving = False def update(self, dt): if not self.moving: self.check_moving() else: self.move(dt) def move(self, dt): delta_x = self.target.x - self.foreshadowed.px delta_y = self.target.y - self.foreshadowed.py distance = Vector(*self.target.pos).distance((self.foreshadowed.px, self.foreshadowed.py)) if distance >= 1.0: delta_x = (delta_x / distance) * (dt * 50) delta_y = (delta_y / distance) * (dt * 50) x, y = self.target.pos x += -delta_x y += -delta_y self.target.set_position(x, y) distance = Vector(*self.target.pos).distance((self.foreshadowed.px, self.foreshadowed.py)) if distance <= 1.0: self.check_moving() def done_moving(self, *args): self.target.set_position(self.foreshadowed.px, self.foreshadowed.py) self.moving = False def highlight_tiles(self, tiles): self.instructions.clear() for tile in tiles: self.instructions.add(Color(rgba=[.3, 1, .3, .3])) self.instructions.add(Rectangle(pos=(tile.px, tile.py), size=(tile.px_width, tile.px_height))) self.target.game.layer_widgets['below'].canvas.add(self.instructions) def check_moving(self, *args): last_axis = self.movement_axis last_cell = self.foreshadowed if self.cells: self.moving = True self.foreshadowed = self.cells.pop() print('moving to', self.foreshadowed.bottomleft) if self.foreshadowed.px != last_cell.px: self.movement_axis = 0 if self.foreshadowed.px < last_cell.px: self.target.set_face('left') self.velocity = [self.target.map.tile_width * -1, 0] else: self.target.set_face('right') self.velocity = [self.target.map.tile_width, 0] elif self.foreshadowed.py != last_cell.py: self.movement_axis = 1 if self.foreshadowed.py < last_cell.py: self.target.set_face('down') self.velocity = [0, self.target.map.tile_width * -1] else: self.target.set_face('up') self.velocity = [0, self.target.map.tile_width] if last_axis != self.movement_axis: print('axis changed!') print(self.target.pos) self.target.set_position(last_cell.px, last_cell.py) print(self.target.pos) print(last_cell.bottomleft, self.foreshadowed.bottomleft) else: self.done_moving() self.end() print('no cells') return self.target.activate_object(target='floor', button_press=False) def end(self): self.target.state = IdleReadyState(self.target) self.instructions.clear()
class Actor(Widget): """ Abstraction of simple Actor Renderer class """ def __init__(self, scene, priority, args, **kwargs): """ Actor constructor """ super(Actor, self).__init__(**kwargs) keys = args.keys() self.size = (0, 0) self.frame_counter = 0 self.collision = False self.debug = False self.sizeUnscaled = (25, 50) self.updateThread = None self.animateThread = None self.doesAnimate = args[ 'doesAnimate'] if 'doesAnimate' in keys else False self.doesUpdate = args['doesUpdate'] if 'doesUpdate' in keys else False self.updateInterval = args[ 'updateInterval'] if 'updateInterval' in keys else 30.0 self.animateInterval = args[ 'animateInterval'] if 'animateInterval' in keys else 30.0 self.pos = (0, 0) self.frame_counter_offset = 0 self.posUnscaled = (0, 0) self.scene = scene self.priority = priority self.canvasSize = self.scene.size self.group = InstructionGroup() self.init = False self.__destroy__ = False self.__resize__(self.canvasSize[0], self.canvasSize[1]) self.count = 0 self.touched = False self.scene.resize_event.append(self.__resize__) self.scene.on_setActive.append(self.__set_intervals__) self.__main_start__() def __main_start__(self): """ Main start function for additional setup after constructor """ self.__start__() self.__pass_start__() def __start__(self): """ *Virtual Function* Override to run functions before object update """ pass def __pass_start__(self): """ End of start set up """ self.init = True self.__set_intervals__(self.scene.isActive()) def __main_update__(self, dt): """ Main update function calls virtual update function """ self.__update__(dt) def __update__(self, dt): """ *Virtual Function* Override for object logic """ print(self, ' is updating without __update__ being overriden') pass def __on_collision__(self, obj): """ called while colliding with object """ self.on_collision(obj) pass def __on_collision_start__(self, obj): """ called at the start of collision """ self.on_collision_start(obj) pass def __on_collision_end__(self, obj): """ called at the end of collision """ self.on_collision_end(obj) pass def on_collision_start(self, obj): """ *Virtual Function* Override for collision start """ pass def on_collision_end(self, obj): """ *Virtual Function* Override for collision end """ pass def on_collision(self, obj): """ *Virtual Function* Override for while colliding """ pass def __main_animate__(self, dt): """ main animation function """ self.__animate__(dt) self.__pass_animate__(dt) def __pass_animate__(self, dt): """ pass animation to render """ self.frame_counter = (self.frame_counter if self.frame_counter < self.animateInterval + self.frame_counter_offset else -1) + 1 pass def on_touch_down(self, touch): """ called when clicked down on self """ if self.collide_point(*touch.pos): self.touched = True self.on_click_down(touch) return True self.touched = False return super(Actor, self).on_touch_down(touch) def on_touch_up(self, touch): """ called when clicked up """ if self.collide_point(*touch.pos): self.touched = False self.on_click_up(touch, True) return True self.touched = False self.on_click_up(touch, False) return super(Actor, self).on_touch_up(touch) def on_touch_move(self, touch): """ called when moving while clicked on self """ if self.collide_point(*touch.pos) and self.touched: self.on_click_move(touch) return True return super(Actor, self).on_touch_move(touch) def on_click_down(self, click): """ *Virtual Function* Override on click down on self """ pass def on_click_move(self, click): """ *Virtual Function* Override on click move on self """ pass def on_click_up(self, click, bHovered): """ *Virtual Function* Override on click down up """ pass def __animate__(self, dt): """ *Virtual Function* Override for animation logic """ print(self, ' is animating without __animate__ being overriden') pass def __main_render__(self): """ Main render loop calls virtual render function then passes instructions to main canvas """ if self.init: self.group.clear() if not self.__destroy__ and self.debug: self.__debug_render__() if not self.__destroy__: self.__render__() self.__pass_render__() def __debug_render__(self): """ *Virtual Function* Override called before __render__ if debug = True """ pass def __pass_render__(self): """ Send drawing instructions to main canvas """ self.canvas.clear() self.canvas.add(self.group) pass def __render__(self): """ *Virtual Function* Override to render custom objects to main canvas """ pass def __set_collision__(self, b): """ enable or disable collision """ if b: self.scene.__add_collision__(self) self.collision = True else: self.scene.__remove_collision__(self) self.collision = False def __end__(self): """ *Virtual Function* Override to run code before object destruction """ pass def destroy(self): """ Called to destroy object """ self.__destroy__ = True if self.updateThread: Clock.unschedule(self.updateThread) if self.animateThread: Clock.unschedule(self.animateThread) self.scene.resize_event.remove(self.__resize__) self.scene.on_setActive.remove(self.__set_intervals__) self.__end__() self.scene.__remove_widget__(self) self.clear_widgets() del self.scene def __resize__(self, x, y): """ Adjust actor size and positions based new canvas resize """ self.canvasSize = self.scene.size self.setPos(self.posUnscaled) self.setSize(self.sizeUnscaled) self.__on_resize__() def __on_resize__(self): """ Called when size of self or window changes """ pass def __set_intervals__(self, b): """ Pause or Resume update/render loops after being set inactive or active Attributes: b (bool): Set active/inactive """ if not self.init: return if not b: if self.doesAnimate and self.animateThread: Clock.unschedule(self.animateThread) self.animateThread = None if self.doesUpdate and self.updateThread: Clock.unschedule(self.updateThread) self.updateThread = None elif b: if self.doesAnimate and self.animateThread is None: self.animateThread = Clock.schedule_interval( self.__main_animate__, 1 / self.animateInterval) if self.doesUpdate and self.updateThread is None: self.updateThread = Clock.schedule_interval( self.__main_update__, 1.0 / self.updateInterval) def setPos(self, p): """ Set object position Attributes: p (tuple) : position to set for actor ( size relative to p/100 * window size + camera position ) """ self.posUnscaled = p self.pos = (((p[0] / 100) * self.canvasSize[0] + self.scene.cameraPos[0]), (p[1] / 100) * self.canvasSize[1] + self.scene.cameraPos[1]) self.__on_resize__() def setPosScaled(self, p): """ set object position relative to window """ self.posUnscaled = ((((100 * p[0] - 100 * self.scene.cameraPos[0]) / self.canvasSize[0]) - self.sizeUnscaled[0] / 2, ((100 * p[1] - 100 * self.scene.cameraPos[1]) / self.canvasSize[1]) - self.sizeUnscaled[1] / 2)) self.setPos(self.posUnscaled) def getCanvasCenter(self): """ Returns tuple of canvas center relative to size """ return (50 - self.sizeUnscaled[0] / 2, 50 - self.sizeUnscaled[1] / 2) def setSize(self, p): """ Set object size Attributes: p (tuple) : size to set for actor ( size relative to p/100 * window size ) """ self.sizeUnscaled = p self.size = ((p[0] / 100) * self.canvasSize[0], (p[1] / 100) * self.canvasSize[1]) self.setPos(self.posUnscaled) def calcResize(self, p, b=False): """ Determine draw size after window rescale """ _p = ((p[0] / 100) * self.canvasSize[0], (p[1] / 100) * self.canvasSize[1]) return _p if not b else min(_p[0], _p[1]) def calcRepos(self, p): """ Determine draw size after window rescale """ _p = ((p[0] / 100) * self.canvasSize[0] + self.scene.cameraPos[0], (p[1] / 100) * self.canvasSize[1] + self.scene.cameraPos[1]) return _p
class SeqGridWidget(Widget): def __init__(self, **kwargs): super(SeqGridWidget, self).__init__(**kwargs) # Change main widget background color Window.clearcolor = get_color_from_hex("#444444") # main widget self.main_lines = [] self.audio_items = [] self.d = 5. self.size_hint = (None, None) self.size = (11100, 11100) self.width = self.size[0] self.height = self.size[1] # grid self.space = 32 self.start = 0 self.amt = (self.width / self.space) * 2 self.drag = False self.selected_item = None # Playhead self.ph = Line(points=[30, self.height, 30, self.height]) self.ph.width = 6 self.inc = 0 self.playhead_increment = 0 self.isPlayheadAdjust = False # loop bars self.loop = False self.loops = InstructionGroup() # self.items = [] # self.grid_lines_main = [] def draw_grid(amt, start, width, height, space): Color(1, 1, 1) # lines that are added to main_lines could be put in # an InstructionGroup and edited later for line spacing for x in range(int(amt)): if x % 4 == 0: # every 4th line is darker # vertical line - thick width Color(.2, .2, .2) L = Line(points=[0 + start, height, 0 + start, 0]) L.width = 2 self.main_lines.append(L) else: Color(.2, .2, .2) # vertical line - normal width L = Line(points=[0 + start, height, 0 + start, 0]) self.main_lines.append(L) start += space Color(.2, .2, .2) # horizontal line L = Line(points=[0, start, width, start]) self.main_lines.append(L) with self.canvas: draw_grid(self.amt, self.start, self.width, self.height, self.space) # Change playhead color to blue # Color(0.25, 0.95, 0.87, 1) # x = get_color_from_hex("#F685BD") Color(0.96, 0.52, 0.74) self.canvas.add(self.ph) with self.canvas: # top grey horizontal bar # controls playhead skipping / looping markers Color(0.43, 0.43, 0.43, 1) Rectangle(pos=(0, self.height - 20), size=(self.width, 20)) def adjust_playhead(self, touch): if touch.y > (self.height - 20): self.isPlayheadAdjust = True self.playhead_increment = touch.x - self.space * 2 p = [touch.x, self.height, touch.x, 0] with self.canvas: self.ph.points = p else: self.isPlayheadAdjust = False # temporarily moves playhead on screen def move_playhead(self): self.playhead_increment += self.space # if playhead reaches end of window width, loop back to beginning # if self.playhead_increment > Window.size[0]: # self.playhead_increment=0 # self.size is for testing inside the widget, Window.size[0] # is normal use if self.playhead_increment > self.size[0]: self.playhead_increment = 0 p = [ 30 + self.playhead_increment, self.height, 30 + self.playhead_increment, 0 ] # print(p) with self.canvas: self.ph.width = 2 self.ph.points = p # Line(points=p) # self.playhead.playhead_line # self.playhead.playhead_line.width=300 # print(self.playhead.playhead_line) # self.playhead.moveX(self.playhead_incremen) def loop_func(self, loop): if loop: Color(0, 1, 1) loopL = Line(points=[30 + 20, self.height, 30 + 20, 0]) loopR = Line(points=[30 + 70, self.height, 30 + 70, 0]) handle_size = (20, 20) top_padding = 20 loopHandleL = Rectangle( pos=(loopL.points[0] - (handle_size[0] / 2), self.height - top_padding), size=handle_size) loopHandleR = Rectangle( pos=(loopR.points[0] - (handle_size[0] / 2), self.height - top_padding), size=handle_size) self.loops.add(loopL) self.loops.add(loopR) self.loops.add(loopHandleL) self.loops.add(loopHandleR) self.canvas.add(self.loops) else: self.canvas.remove(self.loops) self.loops.clear() def show_audio_items_stats(self): print("*" * 20) for item in self.audio_items: print("Block pos", item.shape.pos) print("Block size", item.shape.size) print("Audio item count: ", len(self.audio_items)) print("*" * 20) def check_click(self, touch, box, button_type): # checks that we're in bounds when a button/rect is pressed # check for right or left buttons res = touch.x >=box.shape.pos[0] and touch.x <= box.shape.pos[0]+box.shape.size[0] \ and touch.y >=box.shape.pos[1] and touch.y <= box.shape.pos[1]+box.shape.size[1] and \ touch.button == button_type return res def on_touch_down(self, touch): super(SeqGridWidget, self).on_touch_down(touch) # enables dragging of playhead self.adjust_playhead(touch) with self.canvas: # if playhead is being moved, don't place a block/rect if self.isPlayheadAdjust == False: for box in self.audio_items: if self.check_click(touch, box, 'left'): self.drag = True self.selected_item = box print("selected item", self.selected_item) print("in bounds") print("left click") if self.check_click(touch, box, 'right'): print("right click") self.selected_item = box idx = self.audio_items.index(self.selected_item) print("IS LABEL", self.audio_items[idx].text) #next(widget for widget in app.root.walk if widget is ...).parent.remove_widget(...) app = App.get_running_app() self.remove_widget(self.audio_items[idx].text) self.remove_widget(self.audio_items[idx]) self.audio_items[idx].clear_widgets() # remove audio item (shape) self.canvas.remove(self.audio_items[idx].shape) # remove audio item (text) print("remove text here") # self.clear_widgets(self.audio_items) # remove audio item self.audio_items.remove(self.audio_items[idx]) # if not dragging and not right button, add new audio item if self.drag == False and touch.button != 'right': box_size = self.space ai = AudioItem( "sounds/snare1.wav", 100, 100, 100, [touch.x - box_size / 2, touch.y - box_size / 2], [box_size, box_size]) # add to audio_item list self.audio_items.append(ai) self.new_check_snap_to_grid(ai, touch) if stress_test: paint_stress_test(self.width, self.height) self.show_audio_items_stats() def on_touch_up(self, touch): self.drag = False def new_check_snap_to_grid(self, item, touch): for line in self.main_lines: lineX = line.points[0] lineY = line.points[1] selShapeX = item.shape.pos[0] selShapeY = item.shape.pos[1] if touch.x > lineX and touch.x <= lineX + self.space: item.shape.pos = (lineX, selShapeY) item.text.pos = (item.shape.pos[0], item.shape.pos[1]) if touch.y > lineY and touch.y <= lineY + self.space: item.shape.pos = (selShapeX, lineY) item.text.pos = (item.shape.pos[0], item.shape.pos[1]) # item.text.size = (32,32) # if selShapeY > lineY + self.space/2 and selShapeY <= lineY + self.space: # item.shape.pos = (selShapeX, lineY) # item.text.pos = (item.shape.pos[0], item.shape.pos[1]) # # snap to vertical line within spacing px amount # if selShapeX > lineX and selShapeX <= lineX + self.space-1: # item.shape.pos = (lineX, selShapeY) # item.text.pos = (item.shape.pos[0], item.shape.pos[1]) # # snap to horizontal line within spacing px amount # elif selShapeY > lineY and selShapeY <= lineY + self.space-1: # item.shape.pos = (selShapeX, lineY) # item.text.pos = (item.shape.pos[0], item.shape.pos[1]) def on_touch_move(self, touch): # if mouse is less than grid height-20, change pos of playhead # on touch drag # if touch.y > (self.height-20): # self.playhead_increment = touch.x - self.space*2 self.adjust_playhead(touch) if self.drag == True: self.selected_item.shape.pos = ( touch.x - self.selected_item.shape.size[0] / 2, touch.y - self.selected_item.shape.size[1] / 2) self.selected_item.text.pos = ( touch.x - self.selected_item.shape.size[0] / 2, touch.y - self.selected_item.shape.size[1] / 2) print("drag " + str(self.selected_item.shape.pos)) self.new_check_snap_to_grid(self.selected_item, touch) else: self.drag = False
class SnakeGame(Widget): score = NumericProperty(0) game_over = ObjectProperty(None) def __init__(self, *args, **kwargs): super(SnakeGame, self).__init__(*args, **kwargs) self.bind(size=self.__draw_background) self.__drawing_instructions = InstructionGroup() def start_game(self): self.score = 0 self.__snake = None self.__fruit = None self.__game_finished = False self.canvas.before.add(self.__drawing_instructions) self.__create_game_objects() self.__event = Clock.schedule_interval(self.__redraw_scene, 1.00 / 60.00) def stop_game(self): self.resources.end_sound.play() self.__game_finished = True self.__event.cancel() self.__show_game_over() def go_to_menu_screen(*args): self.manager.current = 'MenuScreen' self.canvas.before.remove(self.__drawing_instructions) self.__drawing_instructions.clear() self.__hide_game_over() Clock.schedule_once(go_to_menu_screen, 3) def __show_game_over(self): self.game_over.opacity = 1 def __hide_game_over(self): self.game_over.opacity = 0 def __redraw_scene(self, time_delta): self.__drawing_instructions.clear() self.__draw_snake() self.__draw_fruit() def __draw_background(self, *args): with self.canvas.before: Rectangle(texture=self.resources.background_texture, pos=self.pos, size=self.size) def __draw_snake(self): for element in self.__snake.body: item = Rectangle(texture=self.resources.snake_body_texture, pos=element.position, size=element.size) self.__drawing_instructions.add(item) item = Rectangle(texture=self.resources.snake_head_texture, pos=self.__snake.head.position, size=self.__snake.head.size) self.__drawing_instructions.add(item) def __draw_fruit(self): item = Rectangle(texture=self.resources.apple_texture, pos=self.__fruit.position, size=self.__fruit.size) self.__drawing_instructions.add(item) def __create_game_objects(self): objects_size = (dp(45), dp(45)) def random_position_in_visible_space(): return (random.randrange(objects_size[0], self.size[0] - objects_size[0]), random.randrange(objects_size[1], self.size[1] - objects_size[1])) if self.__snake is None: self.__snake = Snake(random_position_in_visible_space(), objects_size) if self.__fruit is None: self.__fruit = Element(random_position_in_visible_space(), objects_size) def on_touch_down(self, event): if self.__snake.head.contains_position(event.pos): event.grab(self) return True return super(SnakeGame, self).on_touch_down(event) def on_touch_move(self, event): if not self.__game_finished and event.grab_current is self: self.__snake.move(event.dpos) self.__serve_collisions() return True return super(SnakeGame, self).on_touch_move(event) def on_touch_up(self, event): if event.grab_current is self: event.ungrab(self) return True return super(SnakeGame, self).on_touch_up(event) def __serve_collisions(self): if self.__snake.head.overlap(self.__fruit): self.resources.score_sound.play() self.score = self.score + 1 self.__snake.extend() self.__fruit = None self.__create_game_objects() if any( (self.__snake.head.overlap(body) for body in self.__snake.body)): self.stop_game()
class LabelBase(ButtonBehavior, Widget): bg_color = ObjectProperty((0, 1, .5, 1)) color = ObjectProperty((0, 0, 0, 1)) text = StringProperty() font_size = StringProperty('30dp') border_size = NumericProperty("3dp") valign = OptionProperty("middle", options=["top", "middle", "bottom"]) halign = OptionProperty("center", options=["left", "center", "right"]) tag = ObjectProperty(None, allowNone=True) clicable = BooleanProperty(False) pres = ObjectProperty(None) def __init__(self, **kargs): super(LabelBase, self).__init__(**kargs) self.__shape_down__ = None __listchild__ = ListProperty([]) def on___listchild__(self, w, val): if self.container != None: for w in self.__listchild__: self.container.add_widget(w) def add_widget(self, widget): if type(widget) is LabelDecorators: super(LabelBase, self).add_widget(widget) else: self.__listchild__.append(widget) def on_color(self, w, val): if "#" in val: val = "".join(val) self.color = get_color_from_hex(val) else: self.color = val def on_bg_color(self, w, val): if "#" in val: val = "".join(val) self.bg_color = get_color_from_hex(val) else: self.bg_color = val def collide_point(self, x, y): return (x > self.x and x < self.x + self.width) and (y > self.y and y < self.y + self.height) def on_touch_down(self, touch, *args): if self.collide_point(touch.x, touch.y) and self.clicable: size = dp(70), dp(70) w, h = size pos = touch.x - w / 2, touch.y - h / 2 if self.__shape_down__ == None: self.__shape_down__ = InstructionGroup(group="__shape_down__") else: self.container.canvas.before.remove(self.__shape_down__) self.__shape_down__.clear() color = Color(0, 0, 0, .4) self.__shape_down__.add(color) self.__shape_down__.add(Ellipse(pos=pos, size=size)) self.container.canvas.before.add(self.__shape_down__) Clock.schedule_once(self.remove_shape_down, .2) press = datetime.now() super(LabelBase, self).on_touch_down(touch) return True def remove_shape_down(self, dt): self.container.canvas.before.remove(self.__shape_down__) self.__shape_down__.clear()
class ReliefCanvas: # (Widget): # also works without Widget/any ancestor """ relief behavior """ relief_ellipse_inner_colors: ReliefColors = ObjectProperty(()) relief_ellipse_inner_lines: NumericProperty = NumericProperty('6sp') relief_ellipse_inner_offset: NumericProperty = NumericProperty('1sp') relief_ellipse_outer_colors: ReliefColors = ObjectProperty(()) relief_ellipse_outer_lines: NumericProperty = NumericProperty('6sp') relief_square_inner_colors: ReliefColors = ObjectProperty(()) relief_square_inner_lines: NumericProperty = NumericProperty('3sp') relief_square_inner_offset: NumericProperty = NumericProperty('1sp') relief_square_outer_colors: ReliefColors = ObjectProperty(()) relief_square_outer_lines: NumericProperty = NumericProperty('3sp') _relief_graphic_instructions: InstructionGroup # attributes provided by the class to be mixed into x: float y: float width: float height: float canvas: Any bind: Any def __init__(self, **kwargs): super().__init__(**kwargs) self.bind(pos=self._relief_refresh) self.bind(size=self._relief_refresh) self.bind(relief_ellipse_inner_colors=self._relief_refresh) self.bind(relief_ellipse_inner_lines=self._relief_refresh) self.bind(relief_ellipse_inner_offset=self._relief_refresh) self.bind(relief_ellipse_outer_colors=self._relief_refresh) self.bind(relief_ellipse_outer_lines=self._relief_refresh) self.bind(relief_square_inner_colors=self._relief_refresh) self.bind(relief_square_inner_lines=self._relief_refresh) self.bind(relief_square_inner_offset=self._relief_refresh) self.bind(relief_square_outer_colors=self._relief_refresh) self.bind(relief_square_outer_lines=self._relief_refresh) self._relief_graphic_instructions = InstructionGroup() def _relief_refresh(self, *_args): """ pos/size or color changed event handler. """ if self._relief_graphic_instructions.length(): self.canvas.after.remove(self._relief_graphic_instructions) self._relief_graphic_instructions.clear() add = self._relief_graphic_instructions.add pos_size = self.x, self.y, self.width, self.height if self.relief_ellipse_inner_colors and self.relief_ellipse_inner_lines: self._relief_ellipse_inner_refresh( add, *self.relief_ellipse_inner_colors, *pos_size) if self.relief_ellipse_outer_colors and self.relief_ellipse_outer_lines: self._relief_ellipse_outer_refresh( add, *self.relief_ellipse_outer_colors, *pos_size) if self.relief_square_inner_colors and self.relief_square_inner_lines: self._relief_square_inner_refresh(add, *self.relief_square_inner_colors, *pos_size) if self.relief_square_outer_colors and self.relief_square_outer_lines: self._relief_square_outer_refresh(add, *self.relief_square_outer_colors, *pos_size) if self._relief_graphic_instructions.length(): self.canvas.after.add(self._relief_graphic_instructions) def _relief_ellipse_inner_refresh(self, add_instruction: Callable, top_color: ColorRGB, bottom_color: ColorRGB, wid_x: float, wid_y: float, wid_width: float, wid_height: float): """ ellipse pos/size or color changed event handler. """ lines = int(self.relief_ellipse_inner_lines) offset = int(self.relief_ellipse_inner_offset) for line in range(1, lines + 1): alpha = 0.9 - (line / lines) * 0.81 line += offset line2 = 2 * line in_x1 = wid_x + line in_y1 = wid_y + line in_width = wid_width - line2 in_height = wid_height - line2 add_instruction(Color(*top_color, alpha)) # inside top left add_instruction( Line(ellipse=[ in_x1, in_y1, in_width, in_height, ANGLE_END, 360 + ANGLE_BEG ])) add_instruction(Color(*bottom_color, alpha)) # inside bottom right add_instruction( Line(ellipse=[ in_x1, in_y1, in_width, in_height, ANGLE_BEG, ANGLE_END ])) def _relief_ellipse_outer_refresh(self, add_instruction: Callable, top_color: ColorRGB, bottom_color: ColorRGB, wid_x: float, wid_y: float, wid_width: float, wid_height: float): """ ellipse pos/size or color changed event handler. """ lines = int(self.relief_ellipse_outer_lines) for line in range(1, lines + 1): alpha = 0.9 - (line / lines) * 0.81 line2 = 2 * line out_x1 = wid_x - line out_y1 = wid_y - line out_width = wid_width + line2 out_height = wid_height + line2 add_instruction(Color(*top_color, alpha)) # outside top left add_instruction( Line(ellipse=[ out_x1, out_y1, out_width, out_height, ANGLE_END, 360 + ANGLE_BEG ])) add_instruction(Color(*bottom_color, alpha)) # outside bottom right add_instruction( Line(ellipse=[ out_x1, out_y1, out_width, out_height, ANGLE_BEG, ANGLE_END ])) def _relief_square_inner_refresh(self, add_instruction: Callable, top_color: ColorRGB, bottom_color: ColorRGB, wid_x: float, wid_y: float, wid_width: float, wid_height: float): """ square pos/size or color changed event handler. """ lines = int(self.relief_square_inner_lines) offset = int(self.relief_square_inner_offset) for line in range(1, lines + 1): alpha = 0.9 - (line / lines) * 0.81 line += offset line2 = 2 * line in_x1 = wid_x + line in_x2 = in_x1 + wid_width - line2 in_y1 = wid_y + line in_y2 = in_y1 + wid_height - line2 add_instruction(Color(*top_color, alpha)) # inside top left add_instruction( Line(points=[in_x1, in_y1, in_x1, in_y2, in_x2, in_y2])) add_instruction(Color(*bottom_color, alpha)) # inside bottom right add_instruction( Line(points=[in_x1, in_y1, in_x2, in_y1, in_x2, in_y2])) def _relief_square_outer_refresh(self, add_instruction: Callable, top_color: ColorRGB, bottom_color: ColorRGB, wid_x: float, wid_y: float, wid_width: float, wid_height: float): """ square pos/size or color changed event handler. """ lines = int(self.relief_square_outer_lines) for line in range(1, lines + 1): alpha = 0.9 - (line / lines) * 0.81 line2 = 2 * line out_x1 = wid_x - line out_x2 = out_x1 + wid_width + line2 out_y1 = wid_y - line out_y2 = out_y1 + wid_height + line2 add_instruction(Color(*top_color, alpha)) # outside upper left add_instruction( Line(points=[out_x1, out_y1, out_x1, out_y2, out_x2, out_y2])) add_instruction(Color(*bottom_color, alpha)) # outside bottom right add_instruction( Line(points=[out_x1, out_y1, out_x2, out_y1, out_x2, out_y2]))
class LineData(object): point_size = 6 on_change = None min = None max = None def __init__(self, data, axis, color=(1, 0, 0), name="Line", units="Hz", **kwargs): self.axis = axis self.axis.add_line(self) self.color = color self.name = name self.units = units if "min" in kwargs: self.min = kwargs["min"] if "max" in kwargs: self.max = kwargs["max"] with self.axis.parent.canvas: Color(*self.color) self.line = Line(width=1.2) self.circles = [] self.circles_draw_group = InstructionGroup() self.axis.parent.canvas.add(self.circles_draw_group) self.data_update(data) def data_update(self, data=None): if data: self.data = data if not self.axis.update(): self.redraw() def redraw(self): x1, y1, x2, y2 = self.axis.parent.rect w, h = x2 - x1, y2 - y1 #add offset x1 += (w / len(self.data)) / 2 x = 0 points = [] if len(self.circles) != len(self.data): self.circles_draw_group.clear() self.circles = [] for __ in range(len(self.data)): circle = Ellipse(size=(self.point_size, self.point_size)) self.circles.append(circle) self.circles_draw_group.add(circle) for y in self.data: point_y = (((y - self.axis.min) / self.axis.delta) * h) + y1 point_x = ((x / len(self.data)) * w) + x1 points.append([point_x, point_y]) self.circles[ x].pos = point_x - self.point_size / 2, point_y - self.point_size / 2 x += 1 self.line.points = points def find_point(self, x, y): def distance(x1, y1, x2, y2): return sqrt((x2 - x1)**2 + (y2 - y1)**2) tx, ty = x - self.point_size / 2, y - self.point_size / 2 min_point = None min_distance = math.inf for i in range(len(self.circles)): dist = distance(tx, ty, *self.circles[i].pos) if dist < min_distance: min_distance = dist min_point = i return min_point, min_distance def edit_point_data(self, point, y): __, y1, __, y2 = self.axis.parent.rect h = y2 - y1 rpos = max(y - y1, 0) / h self.set_point_value(point, rpos * self.axis.delta + self.axis.min) def get_point_xy(self, point): x, y = self.circles[point].pos return x + self.point_size / 2, y + self.point_size / 2 def get_name_format(self): return self.name, self.format def get_point_value(self, point): return self.data[point] def set_point_value(self, point, value): if not self.axis.auto_max: if value > self.axis.max: value = self.axis.max if not self.axis.auto_min: if value < self.axis.min: value = self.axes.min if self.max is not None: if value > self.max: value = self.max if self.min is not None: if value < self.min: value = self.min self.data[point] = value if self.on_change: self.on_change(point, value) self.data_update()
class EntityFollow(State): def __init__(self, target, following): super(EntityFollow, self).__init__(target) self.following = following self.cells = [] self.moving = False self.instructions = InstructionGroup() targeted = self.target.map.layers.by_name['below'].get_at( *self.following.pos) # targeted = self.target.map.layers.by_name['below'].get_neighbor_cells(following_cell)[0] origin_cell = self.target.map.layers.by_name['below'].get_at( *self.target.pos) if targeted is not None and targeted.tile.is_passable(): cells = targeted.layer.a_star_search(origin_cell, targeted) # if there's only two cells selected, and goal is not origin neighbor... then run away, RUN AWAY! if len(cells ) == 2 and targeted not in self.target.map.layers.by_name[ 'below'].get_neighbor_cells(origin_cell): return if len(cells) > 1: cells.reverse() # self.instructions.clear() self.instructions = InstructionGroup() # self.highlight_tiles(cells) self.cells = cells self.moving = False if not self.cells: print('no cells here dawg') self.target.state = EntityIdle(self.target) self.end() return # self.highlight_tiles(self.cells) self.foreshadowed = None self.velocity = [0, 0] self.target.anim_delay = .2 self.task = Clock.schedule_interval(self.slow_update, .6) def slow_update(self, *args): print([self.following.pos]) distance = Vector(*self.target.pos).distance(self.following.pos) if distance < 100: pass else: self.moving = False # self.instructions.clear() self.target.set_position(self.foreshadowed.px, self.foreshadowed.py) if distance > 500: self.target.state = EntityIdle(self.target) self.end() else: self.target.state = EntityFollow(self.target, self.following) self.end() def update(self, dt): if not self.moving: if self.cells: self.foreshadowed = self.cells.pop() print('moving to', self.foreshadowed) # if self.foreshadowed.occupied: # self.end() if self.foreshadowed.px != self.target.x: if self.foreshadowed.px < self.target.x: self.target.set_face('left') self.velocity = [self.target.map.tile_width * -1, 0] else: self.target.set_face('right') self.velocity = [self.target.map.tile_width, 0] elif self.foreshadowed.py != self.target.y: if self.foreshadowed.py < self.target.y: self.target.set_face('down') self.velocity = [0, self.target.map.tile_width * -1] else: self.target.set_face('up') self.velocity = [0, self.target.map.tile_width] self.start_moving() else: self.end() self.target.get_current_cell() self.target.state = EntityIdle(self.target) else: self.move(dt) def move(self, dt): done = move(dt, self.target, self.foreshadowed.px, self.foreshadowed.py) if done: self.done_moving() def done_moving(self, *args): self.target.set_position(self.foreshadowed.px, self.foreshadowed.py) self.moving = False def highlight_tiles(self, tiles): self.instructions.clear() for tile in tiles: self.instructions.add(Color(rgba=[.3, 1, .3, .3])) self.instructions.add( Rectangle(pos=(tile.px, tile.py), size=(tile.px_width, tile.px_height))) self.target.game.layer_widgets['below'].canvas.add(self.instructions) def start_moving(self, *args): print('start moving') self.moving = True def end(self): super(EntityFollow, self).end() self.task.cancel()
class EntityFollow(State): def __init__(self, target, following): super(EntityFollow, self).__init__(target) self.following = following self.cells = [] self.moving = False self.instructions = InstructionGroup() targeted = self.target.map.layers.by_name['below'].get_at(*self.following.pos) # targeted = self.target.map.layers.by_name['below'].get_neighbor_cells(following_cell)[0] origin_cell = self.target.map.layers.by_name['below'].get_at(*self.target.pos) if targeted is not None and targeted.tile.is_passable(): cells = targeted.layer.a_star_search(origin_cell, targeted) # if there's only two cells selected, and goal is not origin neighbor... then run away, RUN AWAY! if len(cells) == 2 and targeted not in self.target.map.layers.by_name['below'].get_neighbor_cells(origin_cell): return if len(cells) > 1: cells.reverse() # self.instructions.clear() self.instructions = InstructionGroup() # self.highlight_tiles(cells) self.cells = cells self.moving = False if not self.cells: print('no cells here dawg') self.target.state = EntityIdle(self.target) self.end() return # self.highlight_tiles(self.cells) self.foreshadowed = None self.velocity = [0, 0] self.target.anim_delay = .2 self.task = Clock.schedule_interval(self.slow_update, .6) def slow_update(self, *args): print([self.following.pos]) distance = Vector(*self.target.pos).distance(self.following.pos) if distance < 100: pass else: self.moving = False # self.instructions.clear() self.target.set_position(self.foreshadowed.px, self.foreshadowed.py) if distance > 500: self.target.state = EntityIdle(self.target) self.end() else: self.target.state = EntityFollow(self.target, self.following) self.end() def update(self, dt): if not self.moving: if self.cells: self.foreshadowed = self.cells.pop() print('moving to', self.foreshadowed) # if self.foreshadowed.occupied: # self.end() if self.foreshadowed.px != self.target.x: if self.foreshadowed.px < self.target.x: self.target.set_face('left') self.velocity = [self.target.map.tile_width * -1, 0] else: self.target.set_face('right') self.velocity = [self.target.map.tile_width, 0] elif self.foreshadowed.py != self.target.y: if self.foreshadowed.py < self.target.y: self.target.set_face('down') self.velocity = [0, self.target.map.tile_width * -1] else: self.target.set_face('up') self.velocity = [0, self.target.map.tile_width] self.start_moving() else: self.end() self.target.get_current_cell() self.target.state = EntityIdle(self.target) else: self.move(dt) def move(self, dt): done = move(dt, self.target, self.foreshadowed.px, self.foreshadowed.py) if done: self.done_moving() def done_moving(self, *args): self.target.set_position(self.foreshadowed.px, self.foreshadowed.py) self.moving = False def highlight_tiles(self, tiles): self.instructions.clear() for tile in tiles: self.instructions.add(Color(rgba=[.3, 1, .3, .3])) self.instructions.add(Rectangle(pos=(tile.px, tile.py), size=(tile.px_width, tile.px_height))) self.target.game.layer_widgets['below'].canvas.add(self.instructions) def start_moving(self, *args): print('start moving') self.moving = True def end(self): super(EntityFollow, self).end() self.task.cancel()
class ProcessSelect(Widget): pid = NumericProperty(-1) chara = ObjectProperty(None) current_process_index = NumericProperty(-1) process_list = [] dive_clock = None finished = BooleanProperty(False) columns = 20 cell_interval = 120 cell_size = (64, 64) # instruction groups cells = None overwrap = None lebels = None # properties about overwrap rectangle overwrap_pos_x = NumericProperty(0) overwrap_pos_y = NumericProperty(0) overwrap_pos = ReferenceListProperty(overwrap_pos_x, overwrap_pos_y) overwrap_size_w = NumericProperty(0) overwrap_size_h = NumericProperty(62) overwrap_size = ReferenceListProperty(overwrap_size_w, overwrap_size_h) overwrap_r = NumericProperty(0.03) overwrap_g = NumericProperty(0.8) overwrap_b = NumericProperty(1) overwrap_a = NumericProperty(0) overwrap_color = ReferenceListProperty(overwrap_r, overwrap_g, overwrap_b, overwrap_a) overwrap_color_anim = None def index_to_pos(self, i): """Calculate position from index""" posx = (i % self.columns) * self.cell_interval posy = int(i / self.columns) * self.cell_interval return posx, posy def pos_to_index(self, pos): i = int(pos[0] / self.cell_interval) + int(pos[1] / self.cell_interval) * 20 if (pos[0] < 0 or pos[1] < 0 or pos[0] > self.columns * self.cell_interval or pos[0] % self.cell_interval > self.cell_size[0] or pos[1] % self.cell_interval > self.cell_size[1] or i >= len(self.process_list)): i = -1 # case of no select or invalid select return i def start(self): """Initialize function.""" try: self.process_list = Process.list() self.process_list.reverse() except: message("エラーが発生しました。管理者権限でこのゲームを実行してみてください。") return self.cells = InstructionGroup() self.overwrap = InstructionGroup() self.lebels = InstructionGroup() i = 0 pid_of_this_program = os.getpid() for proc in self.process_list: # calculate position posx, posy = self.index_to_pos(i) # draw squares if proc["pid"] == pid_of_this_program: self.cells.add(Color(0.8, 0.8, 0.8)) else: self.cells.add(Color(1, 1, 1)) self.cells.add(Rectangle(pos=(posx, posy), size=self.cell_size)) # draw text self.lebels.add(Color(0, 0, 0)) self.lebels.add( draw_text_on_canvas(str(proc["pid"]), pos=(posx, posy))) i += 1 self.canvas.add(self.cells) self.canvas.add(self.overwrap) self.canvas.add(self.lebels) def update(self, dt): """Frame update function.""" coord = self.chara.coordinate if self.finished is True: return # calculate the index of selected process i = self.pos_to_index(coord) # if selected process changed if i != self.current_process_index: self.time_left = 1 self.current_process_index = i # progress rectangle if i != -1: self.overwrap_color_anim = Animation(overwrap_a=1, overwrap_size_w=62, duration=2.) self.dive_clock = Clock.schedule_once(partial(self.dive, i), 2.) self.overwrap_color_anim.start(self) posx, posy = self.index_to_pos(i) self.overwrap_pos_x = posx + 1 self.overwrap_pos_y = posy + 1 else: self.overwrap_a = 0 self.overwrap_size_w = 0 self.overwrap_color_anim.stop(self) self.dive_clock.cancel() # draw overwrap self.overwrap.clear() self.overwrap.add(Color(*self.overwrap_color)) self.overwrap.add( Rectangle(pos=self.overwrap_pos, size=self.overwrap_size)) def dive(self, index, _): """Diving function.""" self.pid = self.process_list[index]["pid"] try: mw = MemWorker(pid=self.pid) regs = list(mw.process.iter_region()) mw.process.read_bytes(regs[0][0], bytes=1) except: posx, posy = self.index_to_pos(index) with self.canvas: Color(0.97, 0.1, 0) draw_text_on_canvas("ERROR", font_size=20, pos=(posx + 1, posy + 30)) else: self.finished = True anim = Animation(opacity=0) def tmp(*args): self.canvas.clear() anim.bind(on_complete=tmp) anim.start(self)
class ButtonBase(ButtonBehavior, Widget): tag = ObjectProperty(None, allownone=True) bgColor = StringProperty('#707070') font_size = StringProperty("30dp") container = ObjectProperty(None) listchild = ListProperty([]) color = ListProperty([1, 1, 1, 1]) shape_up = ObjectProperty(None) shape_down = ObjectProperty(None) border_size = NumericProperty(5) def __init__(self, **kargs): super(ButtonBase, self).__init__(**kargs) def on_color(self, w, val): if "#" in val: val = "".join(val) self.color = get_color_from_hex(val) else: self.color = val def on_border_size(self, w, v): if self.container: self.container.size = (self.container.parent.width - self.border_size, self.container.parent.height - self.border_size) def on_container(self, root, val): self.container.bind(pos=self.on_container_pos) self.container.size = (self.container.parent.width - self.border_size, self.container.parent.height - self.border_size) for w in self.listchild: self.container.add_widget(w) self.draw_color() def on_listchild(self, w, val): if self.container != None: for w in self.listchild: self.container.add_widget(w) def add_widget(self, widget): if type(widget) is Decorators: super(ButtonBase, self).add_widget(widget) else: self.listchild.append(widget) def on_container_pos(self, root, val): if self.shape_up == None: self.shape_up = InstructionGroup(grup="shape_up") else: self.container.canvas.before.remove(self.shape_up) self.shape_up.clear() self.draw_color() def on_bgColor(self, root, val): if self.shape_up == None: self.shape_up = InstructionGroup(grup="shape_up") else: self.container.canvas.before.remove(self.shape_up) self.shape_up.clear() self.draw_color() def draw_color(self): if self.container and self.shape_up: size = self.container.size color = Color() color.rgb = get_color_from_hex(self.bgColor) self.shape_up.add(color) self.shape_up.add(Rectangle(pos=self.container.pos, size=size)) self.container.canvas.before.add(self.shape_up) def collide_point(self, x, y): return (x > self.x and x < self.x + self.width) and (y > self.y and y < self.y + self.height) def on_touch_down(self, touch, *args): super(ButtonBase, self).on_touch_down(touch) if self.collide_point(touch.x, touch.y): size = self.container.size if self.shape_down == None: self.shape_down = InstructionGroup(group="shape_down") else: self.container.canvas.before.remove(self.shape_down) self.shape_down.clear() color = Color(0, 0, 0, .4) self.shape_down.add(color) self.shape_down.add(Rectangle(pos=self.container.pos, size=size)) self.container.canvas.before.add(self.shape_down) Clock.schedule_once(self.remove_shape_down, .05) return True def remove_shape_down(self, dt): self.container.canvas.before.remove(self.shape_down) self.shape_down.clear()
class Axis(object): min = 0 max = 100 step = 10 auto_min = True auto_max = True format = "%1.0f" left = True def __init__(self, parent, **kwargs): self.lines = [] self.parent = parent self.parent.add_axis(self) self.ruler_lines = [] self.ruler_labels = [] self.ruler_draw_group = InstructionGroup() self.parent.canvas.add(self.ruler_draw_group) if "min" in kwargs: self.min = kwargs["min"] if "max" in kwargs: self.max = kwargs["max"] if "step" in kwargs: self.step = kwargs["step"] if "auto_min" in kwargs: self.auto_min = kwargs["auto_min"] if "auto_max" in kwargs: self.auto_max = kwargs["auto_max"] if "left" in kwargs: self.left = kwargs["left"] if "format" in kwargs: self.format = kwargs["format"] self.delta = self.max - self.min def add_line(self, line): self.lines.append(line) def redraw_ruler(self): x1, y1, x2, y2 = self.parent.rect h = y2 - y1 if len(self.ruler_lines) != int(self.delta / self.step) - 1: self.ruler_draw_group.clear() self.ruler_lines = [] for label in self.ruler_labels: self.parent.remove_widget(label) self.ruler_labels = [] for __ in range(int(self.delta / self.step) - 1): if self.left: line = Line(dash_offset=5) else: line = Line() self.ruler_lines.append(line) self.ruler_draw_group.add(line) label = LabelB() if self.left: label.halign = "right" else: label.halign = "left" self.parent.add_widget(label) self.ruler_labels.append(label) for i in range(int(self.delta / self.step) - 1): y = y1 + (h / ((self.delta / self.step) - 1)) * (i + 1) if self.left: self.ruler_lines[i].points = [x1, y, x2, y] else: self.ruler_lines[i].points = [x2 - 5, y, x2 + 5, y] val = self.min + (self.delta / (int(self.delta / self.step) - 1)) * (i + 1) label = self.ruler_labels[i] label.center_y = y label.text = self.format % val if self.left: label.x = x1 - label.width - 5 else: label.x = x2 + 5 def redraw(self): self.redraw_ruler() for line in self.lines: line.redraw() def update(self): """Update min/max for axis Note:r = ListProperty([1,1,1,1]) It will redraw the lines and axis if update was performed otherwise you will need handle the update yourself Returns: True - if there was change in min/max, False otherwise """ if not self.auto_min and not self.auto_max: return local_min = +math.inf local_max = -math.inf for line in self.lines: if len(line.data): local_min = min(local_min, min(line.data)) local_max = max(local_max, max(line.data)) #adjust to step m = math.ceil(local_min / self.step) - 1 local_min = self.step * m m = math.floor(local_max / self.step) + 1 local_max = self.step * m if self.min != local_min or self.max != local_max: if self.auto_min: self.min = local_min if self.auto_max: self.max = local_max self.delta = self.max - self.min self.redraw() return True return False def find_point(self, x, y): min_distance = math.inf min_point = None min_line = None for line in self.lines: point, distance = line.find_point(x, y) if distance < min_distance: min_point = point min_line = line min_distance = distance return min_point, min_line, min_distance
class PuzzleGameWidget(Widget): tock = 0 last_state = None event = None texture2 = "" texture = "" bkg = StringProperty() piece_group = None last_t = 0 padding = [0, 0, 0, 0] def __init__(self, **kwargs): super(PuzzleGameWidget, self).__init__(**kwargs) self.bkg = "data/images/steampunk-bkg.png" app = App.get_running_app() self.atlas = app.default_atlas self.piece = app.piece self.board = app.game_board self.piece_group = InstructionGroup() self.canvas.add(self.piece_group) Clock.schedule_interval(self.next_state, .1) def set_level(self, level): app = App.get_running_app() app.level_name = level if path.isfile( path.join( getcwd(), "data/images/{}-bkg.png".format( App.get_running_app().level_name))): app.level_bkg = path.join( getcwd(), "data/images/{}-bkg.png".format( App.get_running_app().level_name)) return app.level_bkg = path.join(getcwd(), 'data/images/steampunk-bkg.png') # default def on_touch_down(self, touch): app = App.get_running_app() su = Window.width / int(App.get_running_app().config.get( 'machinewerkz', 'cols')) _x, _y = touch.pos x, y = _x / su, _y / su app.modify_state([int(x), int(y)]) @mainthread def draw_method(self, grid): # update InstructionGroup() for widget canvas app = App.get_running_app() su = Window.width / int(app.config.get('machinewerkz', 'cols')) padding = self.padding[-1] self.piece_group.clear() for y in range(len(grid)): for x in range(len(grid[0])): lit = [False, True][int(grid[y][x])] if lit: if (x, y) in self.piece.test(): tile = self.atlas["{}2".format(app.level_name)] else: tile = self.atlas[app.level_name] self.piece_group.add( Rectangle(texture=tile, pos=((x * su), Window.height - ((y * su) + padding)), size=[su, su])) return grid @mainthread def next_state(self, dt): app = App.get_running_app() f_speed = app.fall_speed ok, msg = self.piece.cb_draw(cb=self.draw_method, acb=app.audio_callback) if not ok: app.audio_callback('fx', 'lock') self.piece.swap_grid() self.piece.shape_shift() self.piece.reset() app.current_score = ' | '.join(self.piece.text_score) return True elapsed = time() - self.last_t if elapsed >= f_speed and self.piece.game_on: self.piece.fall() self.last_t = time()
class Beam(): enemies = [] player1 = None player2 = None def __init__(self, player1, player2, **kwargs): self.canvas = InstructionGroup() self.beamColor = Color(0.0, 0.0, 0.0, 1.0) self.beamGroup = InstructionGroup() self.beamThickness = 40 self.canvas.add(self.beamGroup) self.player1 = player1 self.player2 = player2 self.beamState = 0 self.isColliding = False def setKeyReport(self, keyReport): self.keyReport = keyReport self.player1.setPlayerKeyReport(keyReport.player1) self.player2.setPlayerKeyReport(keyReport.player2) def setIsColliding(self, isColliding): self.isColliding = isColliding def reset(self): self.beamState = 0 self.isColliding = False def updateBeamState(self): bothButton1 = self.keyReport.player1.button1 and self.keyReport.player2.button1 bothButton2 = self.keyReport.player1.button2 and self.keyReport.player2.button2 beamState = self.beamState if not bothButton1 and not bothButton2: beamState = 0 else: beamState = 1 isChanged = False if not beamState == self.beamState: isChanged = True self.beamState = beamState return isChanged def updateBeam(self, p1Pos, p2Pos): xDelta = p2Pos[0] - p1Pos[0] yDelta = p2Pos[1] - p1Pos[1] distanceSquared = math.pow(xDelta, 2) + math.pow(yDelta, 2) theta = math.atan2(yDelta, xDelta) distance = math.sqrt(distanceSquared) self.beamGroup.clear() self.beamGroup.add(PushMatrix()) self.beamGroup.add(self.beamColor) self.beamGroup.add(Translate(p1Pos[0], p1Pos[1], 0)) self.beamGroup.add(Rotate(theta * 180 / math.pi, 0, 0, 1)) self.beamGroup.add(Scale(distance, self.beamThickness, 1)) self.beamGroup.add(Rectangle(pos=(0, -0.5), size=(1, 1))) self.beamGroup.add(PopMatrix()) def update(self, dt): beamLineCoords = (self.player2.pos[0], self.player2.pos[1], self.player1.pos[0], self.player1.pos[1]) if self.isColliding: self.beamColor.r = 0.8 self.beamColor.g = 0.5 self.beamColor.b = 0.3 self.beamColor.a = 1 else: self.beamColor.r = 0.3 self.beamColor.g = 0.3 self.beamColor.b = 0.3 self.beamColor.a = 1 self.updateBeamState() if self.beamState == 0: self.beamThickness = 1 elif self.beamState == 1: self.beamThickness = 40 self.updateBeam(self.player1.pos, self.player2.pos)
class ButtonBase(ButtonBehavior, Widget): #Para guardar datos en el boton y recuperarlas #despues en el evento. tag = ObjectProperty(None, allownone=True) #Colores del boton texto y fondo acepta hexadecimal y rgba bg_color = ObjectProperty([.5, .5, .5, 1]) color = ObjectProperty([1, 1, 1, 1]) font_size = ObjectProperty("20dp") border_size = NumericProperty('3dp') __container__ = ObjectProperty(None) __listchild__ = ListProperty([]) __shape_up__ = ObjectProperty(None) __shape_down__ = ObjectProperty(None) def __init__(self, **kargs): super(ButtonBase, self).__init__(**kargs) def on_color(self, w, val): if "#" in val: val = "".join(val) self.color = get_color_from_hex(val) else: self.color = val def on_border_size(self, w, v): if self.__container__: self.__container__.size = (self.__container__.parent.width - self.border_size, self.__container__.parent.height - self.border_size) def on___container__(self, root, val): self.__container__.bind(pos=self.on___container___pos) self.__container__.size = (self.__container__.parent.width - self.border_size, self.__container__.parent.height - self.border_size) for w in self.__listchild__: self.__container__.add_widget(w) self.draw_color() def on___listchild__(self, w, val): if self.__container__ != None: for w in self.__listchild__: self.__container__.add_widget(w) def add_widget(self, widget): if type(widget) is Decorators: super(ButtonBase, self).add_widget(widget) else: self.__listchild__.append(widget) def on___container___pos(self, root, val): if self.__shape_up__ == None: self.__shape_up__ = InstructionGroup(grup="__shape_up__ ") else: self.__container__.canvas.before.remove(self.__shape_up__) self.__shape_up__.clear() self.draw_color() def on_bg_color(self, root, val): if "#" in val: val = "".join(val) self.bg_color = get_color_from_hex(val) else: self.bg_color = val if get_hex_from_color(self.bg_color) <= "#33333333": self.color = (1, 1, 1, 1) else: self.color = (0, 0, 0, 1) if self.__shape_up__ == None: self.__shape_up__ = InstructionGroup(grup="__shape_up__ ") else: self.__container__.canvas.before.remove(self.__shape_up__) self.__shape_up__.clear() self.draw_color() def draw_color(self): if self.__container__ and self.__shape_up__: size = self.__container__.size color = Color(*self.bg_color) self.__shape_up__.add(color) self.__shape_up__.add( Rectangle(pos=self.__container__.pos, size=size)) self.__container__.canvas.before.add(self.__shape_up__) def collide_point(self, x, y): return (x > self.x and x < self.x + self.width) and (y > self.y and y < self.y + self.height) def on_press(self): size = self.__container__.size if self.__shape_down__ == None: self.__shape_down__ = InstructionGroup(group="__shape_down__") else: self.__container__.canvas.before.remove(self.__shape_down__) self.__shape_down__.clear() color = Color(0, 0, 0, .4) self.__shape_down__.add(color) self.__shape_down__.add( Rectangle(pos=self.__container__.pos, size=size)) self.__container__.canvas.before.add(self.__shape_down__) super(ButtonBase, self).on_press() def on_release(self): self.__container__.canvas.before.remove(self.__shape_down__) self.__shape_down__.clear() super(ButtonBase, self).on_release()