def touch_to_index(self, tx, ty): tx -= self.x ty -= self.y js = self.jewel_size return ( boundary(0, SIZE, int(tx / js)), boundary(0, SIZE, int(ty / js)))
def test_boundary(self): x = boundary(-1000, 0, 100) self.assertEqual(x, 0) x = boundary(1000, 0, 100) self.assertEqual(x, 100) x = boundary(50, 0, 100) self.assertEqual(x, 50)
def find_indeces(self, index): # relative to widget x = index.x - self.x y = index.y - self.y size = self.item_size return I(boundary(0, self.length, int(x / size)), boundary(0, self.length, int(y / size)))
def calc_destination(self, angle): # calculate the path until the bullet hits the edge of the screen win = self.get_parent_window() left = 150.0 * win.width / 1920.0 right = win.width - 236.0 * win.width / 1920.0 top = win.height - 50.0 * win.height / 1920.0 bottom = 96.0 * win.height / 1920.0 bullet_x_to_right = right - self.center_x bullet_x_to_left = left - self.center_x bullet_y_to_top = top - self.center_y bullet_y_to_bottom = bottom - self.center_y destination_x = 0 destination_y = 0 # this is a little bit ugly, but i couldn't find a nicer way in the hurry if 0 <= self.angle < pi/2: # 1st quadrant if self.angle == 0: destination_x = bullet_x_to_right destination_y = 0 else: destination_x = boundary(bullet_y_to_top / tan(self.angle), bullet_x_to_left, bullet_x_to_right) destination_y = boundary(tan(self.angle) * bullet_x_to_right, bullet_y_to_bottom, bullet_y_to_top) elif pi/2 <= self.angle < pi: # 2nd quadrant if self.angle == pi/2: destination_x = 0 destination_y = bullet_y_to_top else: destination_x = boundary(bullet_y_to_top / tan(self.angle), bullet_x_to_left, bullet_x_to_right) destination_y = boundary(tan(self.angle) * bullet_x_to_left, bullet_y_to_bottom, bullet_y_to_top) elif pi <= self.angle < 3*pi/2: # 3rd quadrant if self.angle == pi: destination_x = bullet_x_to_left destination_y = 0 else: destination_x = boundary(bullet_y_to_bottom / tan(self.angle), bullet_x_to_left, bullet_x_to_right) destination_y = boundary(tan(self.angle) * bullet_x_to_left, bullet_y_to_bottom, bullet_y_to_top) elif self.angle >= 3*pi/2: # 4th quadrant if self.angle == 3*pi/2: destination_x = 0 destination_y = bullet_y_to_bottom else: destination_x = boundary(bullet_y_to_bottom / tan(self.angle), bullet_x_to_left, bullet_x_to_right) destination_y = boundary(tan(self.angle) * bullet_x_to_right, bullet_y_to_bottom, bullet_y_to_top) # because all of the calculations above were relative, add the bullet position to it. destination_x += self.center_x destination_y += self.center_y return (destination_x, destination_y)
def bind_x_on_keyboard(self, x): # bind the fingers position to a real possible keyboard location. # get the parent window to look up the screen size. win = self.get_parent_window() bounded_x = x # if on the left side of the keyboard if self.x > 0: bounded_x = boundary(x, self.x, win.width) # if on the right side of the keyboard elif self.x < win.width - self.width: bounded_x = boundary(x, 0, self.x + self.width) return bounded_x
def get_cursor_from_xy(self, x, y): '''Return the (col, row) of the cursor from an (x, y) position. ''' padding_left = self.padding[0] padding_top = self.padding[1] l = self._lines dy = self.line_height + self.line_spacing cx = x - self.x scrl_y = self.scroll_y scrl_x = self.scroll_x scrl_y = scrl_y / dy if scrl_y > 0 else 0 cy = (self.top - padding_top + scrl_y * dy) - y cy = int(boundary(round(cy / dy - 0.5), 0, len(l) - 1)) _get_text_width = self._get_text_width _tab_width = self.tab_width _label_cached = self._label_cached # Offset for horizontal text alignment xoff = 0 halign = self.halign base_dir = self.base_direction or self._resolved_base_dir auto_halign_r = halign == 'auto' and base_dir and 'rtl' in base_dir if halign == 'center': viewport_width = self.width - padding_left - self.padding[2] # _r xoff = int((viewport_width - self._get_row_width(cy)) / 2) elif halign == 'right' or auto_halign_r: viewport_width = self.width - padding_left - self.padding[2] # _r xoff = viewport_width - self._get_row_width(cy) for i in range(0, len(l[cy])): if xoff + _get_text_width(l[cy][:i], _tab_width, _label_cached) + \ (_get_text_width(l[cy][i], _tab_width, _label_cached) -\ _get_text_width('', _tab_width, _label_cached)) * 0.6 +\ padding_left > cx + scrl_x: cx = i break return cx, cy
def update_angle(self, widget, touch): touch_x, touch_y = touch.x, touch.y angle = math.atan2(touch_y - self.cannon.y, touch_x - self.cannon.y) angle = 90 - angle * 180 / math.pi angle = boundary(angle, -85.0, 85.0) self.cannon_angle.value = angle self.update()
def on_touch_move(self, touch): ud = touch.ud if not 'tank_touch' in ud: return False if 'rotation_mode' in ud: # if the current touch is already in the 'rotate' mode, rotate the tower. dx = touch.x - self.center_x dy = touch.y - self.center_y angle = boundary(atan2(dy, dx) * 360 / 2 / pi, -60, 60) angle_change = self.tank_tower_scatter.rotation - angle rotation_matrix = Matrix().rotate(-radians(angle_change), 0, 0, 1) self.tank_tower_scatter.apply_transform(rotation_matrix, post_multiply=True, anchor=(105, 15)) elif touch.x > self.right: # if the finger moved too far to the right go into rotation mode ud['rotation_mode'] = True else: # if the user wants only to drag the tank up and down, let him do it! self.y += touch.dy pass
def changeAngle(self, touch): maxAngle = 155 minAngle = 25 #calculates the angle i radians from x, and y values angle = atan2(touch.y - self.center_y, touch.x - self.center_x ); #radians to degrees angle = angle * (180/pi); #if user clicks below the shooter, move it to the lowest right/left position if angle < 180 and angle > -180: self.shooterTowerAngle = maxAngle - 90 self.shootDirectionAngle = maxAngle if angle < minAngle and angle >= - 90: self.shooterTowerAngle = minAngle - 90 self.shootDirectionAngle = minAngle #Limit a value between a minvalue and maxvalue, for how far the shooter can rotate angle = boundary(angle, 0, 360) #boundary(value, minvalue, maxvalue) Limit a value between a minvalue and maxvalue. if angle < maxAngle and angle > minAngle: self.shooterTowerAngle = angle - 90 self.shootDirectionAngle = angle
def get_cursor_from_xy(self, x, y): '''Return the (row, col) of the cursor from an (x, y) position. ''' padding_left = self.padding[0] padding_top = self.padding[1] l = self._lines dy = self.line_height + self.line_spacing cx = x - self.x scrl_y = self.scroll_y scrl_x = self.scroll_x scrl_y = scrl_y / dy if scrl_y > 0 else 0 cy = (self.top - padding_top + scrl_y * dy) - y cy = int(boundary(round(cy / dy - 0.5), 0, len(l) - 1)) # CHANGE MADE HERE! cx = cx - self._line_offsets[cy] dcx = 0 _get_text_width = self._get_text_width _tab_width = self.tab_width _label_cached = self._label_cached for i in range(1, len(l[cy]) + 1): if _get_text_width(l[cy][:i], _tab_width, _label_cached) + padding_left >= cx + scrl_x: break dcx = i cx = dcx return cx, cy
def on_collision_with_deflector(self, deflector, deflector_vector): self.parent.app.sound['deflection'].play() # flash up the deflector Animation.stop_all(deflector.point1, 'color') Animation.stop_all(deflector.point2, 'color') deflector.point1.color = (1, 1, 1, 1) deflector.point2.color = (1, 1, 1, 1) animation = Animation(color=(0, 0, 1, 1), duration=3, t='out_expo') animation.start(deflector.point1) animation.start(deflector.point2) # calculate deflection angle impact_angle = (radians(deflector_vector.angle(Vector(1, 0))) % pi) - (self.angle % pi) self.angle = (self.angle + 2 * impact_angle) % (2 * pi) destination = self.calc_destination(self.angle) speed = boundary( self.parent.app.config.getint('GamePlay', 'BulletSpeed'), 1, 10) self.animation = self.create_animation(speed, destination) # start the animation self.animation.start(self) self.animation.bind(on_complete=self.on_collision_with_edge)
def tab_bar_autoscroll(self, target, step): # automatic scroll animation of the tab bar. bound_left = self.center_x bound_right = self.layout.width - bound_left dt = target.center_x - bound_left sx, sy = self.scrollview.convert_distance_to_scroll(dt, 0) # last scroll x of the tab bar lsx = self.last_scroll_x # determine scroll direction scroll_is_late = lsx < sx # distance to run dst = abs(lsx - sx) * step if not dst: return if scroll_is_late and target.center_x > bound_left: x = lsx + dst elif not scroll_is_late and target.center_x < bound_right: x = lsx - dst else: return x = boundary(x, 0.0, 1.0) self.scrollview.goto(x, None)
def tab_bar_autoscroll(self, target, step): # automatic scroll animation of the tab bar. bound_left = self.center_x bound_right = self.layout.width - bound_left dt = target.center_x - bound_left sx, sy = self.scrollview.convert_distance_to_scroll(dt, 0) # last scroll x of the tab bar lsx = self.last_scroll_x # determine scroll direction scroll_is_late = lsx < sx # distance to run dst = abs(lsx - sx) * step if not dst: return if scroll_is_late and target.center_x > bound_left: x = lsx + dst elif not scroll_is_late and target.center_x < bound_right: x = lsx - dst x = boundary(x, 0.0, 1.0) self.scrollview.goto(x, None)
def displaySettingsScreen(self): self.settingsPopupDismissed = False # the first time the setting dialog is called, initialize its content. if self.settingsPopup is None: self.settingsPopup = Popup(attach_to=self, title= 'DBShooter Settings' ) self.settingDialog = SettingDialog(root=self) self.settingsPopup.content = self.settingDialog self.settingDialog.music_slider.value = boundary(self.app.config.getint('General', 'Music'), 0, 100) self.settingDialog.sound_slider.value = boundary(self.app.config.getint('General', 'Sound'), 0, 100) self.settingsPopup.open()
def set_ray_angle(self, widget, touch): touch_x, touch_y = touch.x, touch.y angle = math.atan2(touch_y - self.line_in.end_y, touch_x - self.line_in.end_x) angle = angle * 180 / math.pi + 180 if angle > 180: angle -= 360 angle = boundary(angle, -85.0, 85.0) self.in_angle.value = angle self.update()
def _set_cursor(self, pos): if not self._lines: self._trigger_refresh_text() return l = self._lines cr = boundary(pos[1], 0, len(l) - 1) cc = boundary(pos[0], 0, len(l[cr])) cursor = cc, cr # adjust scrollview to ensure that the cursor will be always inside our # viewport. padding_left = self.padding[0] padding_right = self.padding[2] viewport_width = self.width - padding_left - padding_right sx = self.scroll_x offset = self.cursor_offset(c=cc, r=cr) # if offset is outside the current bounds, readjust if offset > viewport_width + sx: self.scroll_x = offset - viewport_width if offset < sx: self.scroll_x = offset if offset < viewport_width * 0.25: self.scroll_x = 0 # do the same for Y # this algo try to center the cursor as much as possible dy = self.line_height + self.line_spacing offsety = cr * dy sy = self.scroll_y padding_top = self.padding[1] padding_bottom = self.padding[3] viewport_height = self.height - padding_top - padding_bottom - dy if offsety > viewport_height + sy: sy = offsety - viewport_height if offsety < sy: sy = offsety self.scroll_y = sy if self._cursor == cursor: return self._cursor = cursor return True
def settings_button_pressed(self): self.app.sound['switch'].play() # the first time the setting dialog is called, initialize its content. if self.setting_popup is None: self.setting_popup = Popup(attach_to=self, title='DeflecTouch Settings', size_hint=(0.3, 0.5)) self.setting_dialog = SettingDialog(root=self) self.setting_popup.content = self.setting_dialog self.setting_dialog.music_slider.value = boundary(self.app.config.getint('General', 'Music'), 0, 100) self.setting_dialog.sound_slider.value = boundary(self.app.config.getint('General', 'Sound'), 0, 100) self.setting_dialog.speed_slider.value = boundary(self.app.config.getint('GamePlay', 'BulletSpeed'), 1, 10) self.setting_popup.open()
def fire(self): destination = self.calc_destination(self.angle) speed = boundary(self.parent.app.config.getint('GamePlay', 'BulletSpeed'), 1, 10) self.animation = self.create_animation(speed, destination) # start the animation self.animation.start(self) self.animation.bind(on_complete=self.on_collision_with_edge) # start to track the position changes self.bind(pos=self.callback_pos)
def fire(self): destination = self.calc_destination(self.angle) speed = boundary( self.parent.app.config.getint('GamePlay', 'BulletSpeed'), 1, 10) self.animation = self.create_animation(speed, destination) # start the animation self.animation.start(self) self.animation.bind(on_complete=self.on_collision_with_edge) # start to track the position changes self.bind(pos=self.callback_pos)
def settings_button_pressed(self): self.app.sound['switch'].play() # the first time the setting dialog is called, initialize its content. if self.setting_popup is None: self.setting_popup = Popup(attach_to=self, title='DeflecTouch Settings', size_hint=(0.3, 0.5)) self.setting_dialog = SettingDialog(root=self) self.setting_popup.content = self.setting_dialog self.setting_dialog.music_slider.value = boundary( self.app.config.getint('General', 'Music'), 0, 100) self.setting_dialog.sound_slider.value = boundary( self.app.config.getint('General', 'Sound'), 0, 100) self.setting_dialog.speed_slider.value = boundary( self.app.config.getint('GamePlay', 'BulletSpeed'), 1, 10) self.setting_popup.open()
def _set_cursor(self, pos): if not self._lines: self._trigger_refresh_text() return l = self._lines cr = boundary(pos[1], 0, len(l) - 1) cc = boundary(pos[0], 0, len(l[cr])) cursor = cc, cr if self._cursor == cursor: return self._cursor = cursor # adjust scrollview to ensure that the cursor will be always inside our # viewport. viewport_width = self.width - self.padding_x * 2 sx = self.scroll_x offset = self.cursor_offset() # if offset is outside the current bounds, reajust if offset > viewport_width + sx: self.scroll_x = offset - viewport_width if offset < sx: self.scroll_x = offset # do the same for Y # this algo try to center the cursor as much as possible dy = self.line_height + self._line_spacing offsety = cr * dy sy = self.scroll_y viewport_height = self.height - self.padding_y * 2 - dy if offsety > viewport_height + sy: sy = offsety - viewport_height if offsety < sy: sy = offsety self.scroll_y = sy return True
def get_cursor_from_xy(self, x, y): '''Return the (row, col) of the cursor from an (x, y) position. ''' l = self._lines dy = self.line_height + self._line_spacing cx = x - self.x cy = (self.top - self.padding_y + self.scroll_y * dy) - y cy = int(boundary(round(cy / dy), 0, len(l) - 1)) dcx = 0 for i in xrange(1, len(l[cy])+1): if self._get_text_width(l[cy][:i]) >= cx: break dcx = i cx = dcx return cx, cy
def get_cursor_from_xy(self, x, y): '''Return the (row, col) of the cursor from an (x, y) position. ''' l = self._lines dy = self.line_height + self._line_spacing cx = x - self.x cy = (self.top - self.padding_y + self.scroll_y * dy) - y cy = int(boundary(round(cy / dy), 0, len(l) - 1)) dcx = 0 for i in xrange(1, len(l[cy]) + 1): if self._get_text_width(l[cy][:i]) >= cx: break dcx = i cx = dcx return cx, cy
def get_cursor_from_index(self, index): '''Return the (row, col) of the cursor from text index ''' index = boundary(index, 0, len(self.text)) if index <= 0: return 0, 0 lf = self._lines_flags l = self._lines i = 0 for row in xrange(len(l)): ni = i + len(l[row]) if lf[row] & FL_IS_NEWLINE: ni += 1 i += 1 if ni >= index: return index - i, row i = ni return index, row
def _get_cursor_from_xy(self, x, y): '''Return the (row, col) of the cursor from an (x, y) position. ''' padding_left = self.padding[0] padding_top = self.padding[1] l = self.lines dy = self.line_height + self.line_spacing cx = x - self.x cy = (self.top - padding_top) - y cy = int(boundary(round(cy / dy - 0.5), 0, len(l) - 1)) _get_text_width = self._get_text_width for i in range(0, len(l[cy])): if _get_text_width(''.join(l[cy][:i])) + \ _get_text_width(l[cy][i]) * 0.6 + \ padding_left > cx: return i, cy return len(l[cy]), cy
def tab_bar_autoscroll(self, instance_tab_label: MDTabsLabel, step: float): # Automatic scroll animation of the tab bar. bound_left = self.center_x - self.x bound_right = self.layout.width - bound_left dt = instance_tab_label.center_x - bound_left sx, sy = self.scrollview.convert_distance_to_scroll(dt, 0) lsx = self.last_scroll_x # ast scroll x of the tab bar scroll_is_late = lsx < sx # determine scroll direction dst = abs(lsx - sx) * step # distance to run if not dst: return if scroll_is_late and instance_tab_label.center_x > bound_left: x = lsx + dst elif not scroll_is_late and instance_tab_label.center_x < bound_right: x = lsx - dst else: return x = boundary(x, 0.0, 1.0) self.scrollview.goto(x, None)
def on_collision_with_deflector(self, deflector, deflector_vector): self.parent.app.sound['deflection'].play() # flash up the deflector Animation.stop_all(deflector.point1, 'color') Animation.stop_all(deflector.point2, 'color') deflector.point1.color = (1, 1, 1, 1) deflector.point2.color = (1, 1, 1, 1) animation = Animation(color=(0, 0, 1, 1), duration=3, t='out_expo') animation.start(deflector.point1) animation.start(deflector.point2) # calculate deflection angle impact_angle = (radians(deflector_vector.angle(Vector(1, 0))) % pi) - (self.angle % pi) self.angle = (self.angle + 2*impact_angle) % (2*pi) destination = self.calc_destination(self.angle) speed = boundary(self.parent.app.config.getint('GamePlay', 'BulletSpeed'), 1, 10) self.animation = self.create_animation(speed, destination) # start the animation self.animation.start(self) self.animation.bind(on_complete=self.on_collision_with_edge)
def bind_y_on_keyboard(self, y): # bind the fingers position to a real possible keyboard location bounded_y = boundary(y, self.y, self.top) return bounded_y
def calc_destination(self, angle): # calculate the path until the bullet hits the edge of the screen win = self.get_parent_window() # the following "magic numbers" are based on the dimensions of the # cutting of the image 'overlay.png' left = 150.0 * win.width / 1920.0 right = win.width - 236.0 * win.width / 1920.0 top = win.height - 50.0 * win.height / 1920.0 bottom = 96.0 * win.height / 1920.0 bullet_x_to_right = right - self.center_x bullet_x_to_left = left - self.center_x bullet_y_to_top = top - self.center_y bullet_y_to_bottom = bottom - self.center_y destination_x = 0 destination_y = 0 # this is a little bit ugly, but I couldn't find a nicer way in the hurry if 0 <= self.angle < pi / 2: # 1st quadrant if self.angle == 0: destination_x = bullet_x_to_right destination_y = 0 else: destination_x = boundary(bullet_y_to_top / tan(self.angle), bullet_x_to_left, bullet_x_to_right) destination_y = boundary( tan(self.angle) * bullet_x_to_right, bullet_y_to_bottom, bullet_y_to_top) elif pi / 2 <= self.angle < pi: # 2nd quadrant if self.angle == pi / 2: destination_x = 0 destination_y = bullet_y_to_top else: destination_x = boundary(bullet_y_to_top / tan(self.angle), bullet_x_to_left, bullet_x_to_right) destination_y = boundary( tan(self.angle) * bullet_x_to_left, bullet_y_to_bottom, bullet_y_to_top) elif pi <= self.angle < 3 * pi / 2: # 3rd quadrant if self.angle == pi: destination_x = bullet_x_to_left destination_y = 0 else: destination_x = boundary(bullet_y_to_bottom / tan(self.angle), bullet_x_to_left, bullet_x_to_right) destination_y = boundary( tan(self.angle) * bullet_x_to_left, bullet_y_to_bottom, bullet_y_to_top) elif self.angle >= 3 * pi / 2: # 4th quadrant if self.angle == 3 * pi / 2: destination_x = 0 destination_y = bullet_y_to_bottom else: destination_x = boundary(bullet_y_to_bottom / tan(self.angle), bullet_x_to_left, bullet_x_to_right) destination_y = boundary( tan(self.angle) * bullet_x_to_right, bullet_y_to_bottom, bullet_y_to_top) # because all of the calculations above were relative, add the bullet position to it. destination_x += self.center_x destination_y += self.center_y return (destination_x, destination_y)
def touch_to_index(self, tx, ty): tx -= self.x ty -= self.y js = self.jewel_size return (boundary(0, SIZE, int(tx / js)), boundary(0, SIZE, int(ty / js)))
def to_focus_space(v): # focus coordinate space is [-1000, 1000] return (boundary(v, 0., 1.) * 2000) - 1000