class Button: def __init__(self): self.buttonOn = ButtonOn() self.buttonOff = ButtonOff() self.isOn = False; self.rect = Rect(0,0,0,0) def get_sprite(self): if self.isOn: return self.buttonOn else: return self.buttonOff def set_x(self, x): self.buttonOn.rect.x = x self.buttonOff.rect.x = x self.rect = self.buttonOn.rect def set_y(self, y): self.buttonOn.rect.y = y self.buttonOff.rect.y = y self.rect = self.buttonOn.rect def check_pressed(self, pressed, x, y): if pressed: if self.rect.collidepoint(x, y): self.isOn = True return self.isOn def check_point(self, x, y): return self.rect.collidepoint(x, y) def set_pressed(self, pressed): self.isOn = pressed
def pick_rect(points, rects): ox, oy = sorted([ (sum(p), p) for p in points ])[0][1] x = ox y = oy ex = None while 1: x += 1 if not (x, y) in points: if ex is None: ex = x - 1 if ((ox, y+1) in points): if x == ex + 1 : y += 1 x = ox else: y -= 1 break else: if x <= ex: y-= 1 break c_rect = Rect(ox*tilewidth,oy*tileheight,\ (ex-ox+1)*tilewidth,(y-oy+1)*tileheight) rects.append(c_rect) rect = Rect(ox,oy,ex-ox+1,y-oy+1) kill = [ p for p in points if rect.collidepoint(p) ] [ points.remove(i) for i in kill ] if points: pick_rect(points, rects)
def get_item_at_pos (self, position): """L.get_item_at_pos (...) -> ListItem Gets the item at the passed position coordinates. """ eventarea = self.rect_to_client () if not eventarea.collidepoint (position): return None position = position[0] - eventarea.left, position[1] - eventarea.top border = base.GlobalStyle.get_border_size \ (self.__class__, self.style, StyleInformation.get ("ACTIVE_BORDER")) * 2 posy = self.vadjustment items = self.scrolledlist.items width = eventarea.width bottom = eventarea.bottom images = self.images spacing = self.scrolledlist.spacing for item in items: rect = Rect (images [item][1]) rect.y = posy rect.width = width + border if rect.bottom > bottom: rect.height = bottom - rect.bottom + border if rect.collidepoint (position): return item posy += images[item][1].height + spacing + border return None
class Slider(Element): """ This is the Slider class. It is an interface object which has a value tied to a movable slider so that the user can change that value. Inherits from the Element class. The constructor takes a position (x, y), size (width, height), barColor(r,g,b), sliderColor (r,g,b), and a value which defaults to 0. Index becomes value (pixel index based on background surface). The actual value that this object holds onto is a float from 0 to 1. """ def __init__(self, x, y, width, height, bar_color, slider_color, value=0): super(Slider, self).__init__(x, y, width, height, bar_color) self.slider_frame = Rect(x, y, 20, self.frame.h) self.slider = Surface(self.slider_frame.size) self.slider_color = slider_color self.slider.fill(self.slider_color) self.value = 1.0 * value / width self.draggable = True self.on_mouse_drag = Signal() self.on_value_changed = Signal() def hit(self, mouse_pos): if not self.slider_frame.collidepoint(mouse_pos): return None else: return self def mouse_drag(self, view, position, event): if view == self: delta = event.rel self.slider_frame.x = min(self.slider_frame.x + delta[0], self.frame.x + self.frame.w - 20) self.slider_frame.x = max(self.slider_frame.x, self.frame.x) self.value = 1.0 * (self.slider_frame.x - self.frame.x) / (+ self.frame.w - 20) self.on_mouse_drag(position, delta) self.on_value_changed() def update_position(self): super(Slider, self).update_position() self.slider_frame = Rect(self.frame.x, self.frame.y, 20, self.frame.h) def set_index(self, index): """ It takes a new index as a value from 0.0 to 1.0. This would be a percentage from min to max for this slider. """ self.slider_frame.x = self.frame.x + index * (self.frame.w - 20) self.value = index if self.value > 1.0: self.value = 1.0 def render(self, window): """ The render method draws this object's surface to the window. The super class draws the background while this object draws the slider at the correct position. """ super(Slider, self).render(window) window.blit(self.slider, self.slider_frame)
def calculateIntersectPoint(p1, p2, p3, p4): p = getIntersectPoint(p1, p2, p3, p4) if p is not None: width = p2[0] - p1[0] height = p2[1] - p1[1] r1 = Rect(p1, (width, height)) r1.normalize() width = p4[0] - p3[0] height = p4[1] - p3[1] r2 = Rect(p3, (width, height)) r2.normalize() tolerance = 1 if r1.width < tolerance: r1.width = tolerance if r1.height < tolerance: r1.height = tolerance if r2.width < tolerance: r2.width = tolerance if r2.height < tolerance: r2.height = tolerance for point in p: try: res1 = r1.collidepoint(point) res2 = r2.collidepoint(point) if res1 and res2: point = [int(pp) for pp in point] return point except: str = "point was invalid ", point print(str) return None else: return None
class GameButton: def __init__(self, action, text): self.action = action self.size = (85, 35) self.fill_color = (0, 180, 0) self.outline_color = (0, 110, 0) self.display_rect = Rect(0, 0, 0, 0) self.text = text self.font = pygame.font.SysFont("Arial", 22) self.isSet = False self.isHover = False def _adjust_color_for_hover(self, color): (r, g, b) = color return (r, g + 60, b) def _adjust_color_for_set(self, color): (r, g, b) = color return (r + 200, g - 100, b) def click_test(self, mouseDownPos): if self.display_rect.collidepoint(mouseDownPos): if self.action(): self.isSet = True else: self.isSet = False def mouse_move_test(self, mousePos): if self.display_rect.collidepoint(mousePos): self.isHover = True else: self.isHover = False def _transform_color(self, color): if self.isHover: color = self._adjust_color_for_hover(color) if self.isSet: color = self._adjust_color_for_set(color) return color def draw(self, surface, topLeft): (x, y) = topLeft self.display_rect = Rect((x, y, self.size[0], self.size[1])) # Draw button rect draw.rect(surface, self._transform_color(self.fill_color), self.display_rect) draw.rect(surface, self._transform_color(self.outline_color), self.display_rect, 4) # Draw text on the button textSize = self.font.size(self.text) textsurface = self.font.render(self.text, True, (0, 0, 0)) textX = topLeft[0] + self.size[0] / 2 - textSize[0] / 2 textY = topLeft[1] + self.size[1] / 2 - textSize[1] / 2 surface.blit(textsurface, (textX, textY))
def CreditsMenu(): music.load(join(f_music, 'Credits_Music.ogg')) music.set_volume(0.5) music.play(loops=-1) check_credits_menu = True coin_animation = 1 coin_animation_control = 0 num_image = 1 y_mov = 0 background_animation_control = 0 button_back = Rect(400, 690, 192, 42) button_cat_sound = Rect(850, 500, 100, 100) while check_credits_menu: CLOCK.tick(60) mouse_pos = mouse.get_pos() for event in pygame.event.get(): if event.type == pygame.QUIT: exit() if event.type == MOUSEBUTTONDOWN and event.button == 1: if button_back.collidepoint(mouse.get_pos()): sfxButtonClick.play() check_credits_menu = False if button_cat_sound.collidepoint(mouse.get_pos()): sfxCat.play() ButtonsPrint(button_cat_sound, ':3', menuFont) SCREEN.blit(scale(load(join(f_backgrounds, f'Credits_{num_image}.png')) .convert_alpha(), (1040, 701)), (0, 80)) y_move = y_mov % imgCredits.get_rect().height SCREEN.blit(imgCredits, (0, (y_move - imgCredits.get_rect().height))) if y_move < Height: SCREEN.blit(imgCredits, (0, y_move)) SCREEN.blit(scale(load(join(f_backgrounds, f'CreditsT_{num_image}.png')) .convert_alpha(), (1040, 701)), (0, 80)) ButtonsPrint(button_back, 'BACK', menuFont) SCREEN.blit(imgCursor, (mouse_pos[0], mouse_pos[1])) SCREEN.blit(bgArcadeMenu, (0, 0)) SCREEN.blit(scale(load(join(f_coin, f'Coin_{coin_animation}.png')) .convert_alpha(), (220, 150)), (370, 855)) y_mov -= 0.75 coin_animation_control += 0.5 background_animation_control += 1 if background_animation_control % 8 == 0: num_image += 1 if num_image == 9: num_image = 1 if coin_animation_control % 6 == 0: coin_animation += 1 if coin_animation > 6: coin_animation = 1 coin_animation_control = 0 display.update() music.stop()
def HowToPlayMenu(): check_how_to_play = True coin_animation = 1 coin_animation_control = 0 x_mov = 0 button_back = Rect(630, 670, 192, 42) bonus_1_sound = Rect(210, 580, 50, 70) bonus_2_sound = Rect(330, 580, 50, 70) bonus_3_sound = Rect(460, 580, 50, 70) fuel_sound = Rect(330, 440, 50, 50) while check_how_to_play: CLOCK.tick(60) mouse_pos = mouse.get_pos() for event in pygame.event.get(): if event.type == pygame.QUIT: exit() if event.type == MOUSEBUTTONDOWN and event.button == 1: if button_back.collidepoint(mouse.get_pos()): sfxButtonClick.play() check_how_to_play = False if bonus_1_sound.collidepoint(mouse.get_pos()): sfxBloodPorky.play() if bonus_2_sound.collidepoint(mouse.get_pos()): sfxBloodOldWoman.play() if bonus_3_sound.collidepoint(mouse.get_pos()): sfxBloodPolice.play() if fuel_sound.collidepoint(mouse.get_pos()): sfxPowerUp.play() ButtonsPrint(bonus_1_sound, '1', menuFont) ButtonsPrint(bonus_2_sound, '2', menuFont) ButtonsPrint(bonus_3_sound, '3', menuFont) ButtonsPrint(fuel_sound, 'F', menuFont) x_move = x_mov % bgHowToPlay.get_rect().width SCREEN.blit(bgHowToPlay, ((x_move - bgHowToPlay.get_rect().width), 70)) if x_move < Width: SCREEN.blit(bgHowToPlay, (x_move, 70)) SCREEN.blit(imgHowToPlay, (0, 0)) ButtonsPrint(button_back, 'BACK', menuFont) SCREEN.blit(imgCursor, (mouse_pos[0], mouse_pos[1])) SCREEN.blit(bgArcadeMenu, (0, 0)) SCREEN.blit(scale(load(join(f_coin, f'Coin_{coin_animation}.png')) .convert_alpha(), (220, 150)), (370, 855)) x_mov -= 5 coin_animation_control += 0.5 if coin_animation_control % 6 == 0: coin_animation += 1 if coin_animation > 6: coin_animation = 1 coin_animation_control = 0 display.update()
def test_collidepoint(self): r = Rect(1, 2, 3, 4) self.assertTrue(r.collidepoint(r.left, r.top), "r does not collide with point (left, top)") self.assertFalse(r.collidepoint(r.left - 1, r.top), "r collides with point (left - 1, top)") self.assertFalse(r.collidepoint(r.left, r.top - 1), "r collides with point (left, top - 1)") self.assertFalse( r.collidepoint(r.left - 1, r.top - 1), "r collides with point (left - 1, top - 1)", ) self.assertTrue( r.collidepoint(r.right - 1, r.bottom - 1), "r does not collide with point (right - 1, bottom - 1)", ) self.assertFalse(r.collidepoint(r.right, r.bottom), "r collides with point (right, bottom)") self.assertFalse( r.collidepoint(r.right - 1, r.bottom), "r collides with point (right - 1, bottom)", ) self.assertFalse( r.collidepoint(r.right, r.bottom - 1), "r collides with point (right, bottom - 1)", )
def calculateIntersectPoint(p1, p2, p3, p4): p = getIntersectPoint(p1, p2, p3, p4) #print p if p is not None: width = p2[0] - p1[0] height = p2[1] - p1[1] r1 = Rect(p1, (width , height)) r1.normalize() width = p4[0] - p3[0] height = p4[1] - p3[1] r2 = Rect(p3, (width, height)) r2.normalize() # Ensure both rects have a width and height of at least 'tolerance' else the # collidepoint check of the Rect class will fail as it doesn't include the bottom # and right hand side 'pixels' of the rectangle tolerance = 1 if r1.width < tolerance: r1.width = tolerance if r1.height < tolerance: r1.height = tolerance if r2.width < tolerance: r2.width = tolerance if r2.height < tolerance: r2.height = tolerance for point in p: try: res1 = r1.collidepoint(point) res2 = r2.collidepoint(point) if res1 and res2: point = [int(pp) for pp in point] return point except: # sometimes the value in a point are too large for PyGame's Rect class #str = "point was invalid ", point #print str pass # This is the case where the infinately long lines crossed but # the line segments didn't return None else: return None
def draw(self, screen, coordinates): """ Draw button widget on a screen with given coordinates Changes color of button when mouse is on a button or when button is clicked. Also, if user clicked a button, self.action would be called. :param screen: pygame screen :param coordinates: tuple (int, int) Coordinates (x, y) where button widget should be drawn """ x, y = coordinates mouse_pos, mouse_click = mouse.get_pos(), mouse.get_pressed() button_rect = Rect(x, y, self.width, self.height) text_coordinates = coordinates if self.centralized: text_rect = self.text.get_rect() text_coordinates = (x + self.width // 2 - text_rect.width // 2, y + self.height // 2 - text_rect.height // 2) if button_rect.collidepoint(mouse_pos[0], mouse_pos[1]): if mouse_click[0]: if self.sound: self.sound.play() draw.rect(screen, self.pressed_bg, button_rect) self.text.draw(screen, text_coordinates) self.action() time.delay(200) else: draw.rect(screen, self.active_bg, button_rect) self.text.draw(screen, text_coordinates) else: draw.rect(screen, self.inactive_bg, button_rect) self.text.draw(screen, text_coordinates)
class Camera(Entity): def __init__(self, instance, target, offset=(0, 0)): Entity.__init__(self, instance) self.target = target self.offset = offset self.last_frames = [] self.rect = Rect(sub_rectangular(self.position, (0, 0)), scale_rectangular(self.offset, -2)) def on_screen(self, o): if o.drawable is not None and o.drawable.image is not None and o.drawable._draw_position is not None: r = Rect(o.drawable._draw_position, (o.drawable.image.get_size())) return r.colliderect(self.rect) return True def point_on_screen(self, o): return self.rect.collidepoint(o) def set_target(self, target): self.target = target for x in range(2): self.last_frames.append(self.target.position) def update(self, delta_time): if self.target is not None: self.position = self.last_frames.pop(0) self.last_frames.append( add_rectangular(self.target.position, self.offset)) self.rect = Rect(sub_rectangular(self.position, (0, 0)), scale_rectangular(self.offset, -2))
def stop_on_tile(pos, stage, player_team): global _block_origin if not _block_origin: return ox, oy = _block_origin tx, ty = pos _block_origin = None left = min((tx, ox)) right = max((tx, ox)) top = min((ty, oy)) bottom = max((ty, oy)) conflicts = False # Check if this conflicts with existing stockpiles. for stock in player_team.stockpiles: sx, sy = stock.x, stock.y sw, sh = stock.width, stock.height if not (sx > right \ or sy > bottom \ or sx + sw <= left \ or sy + sh <= top): conflicts = True break # Also check if there are no designations on the stockpile. rect = Rect(left, top, right - left + 1, bottom - top + 1) for designation in player_team.designations: if not designation['done'] \ and rect.collidepoint(designation['location']): conflicts = True all_walkable = True for y in range(top, bottom + 1): for x in range(left, right + 1): if x < 0 or x >= stage.width or \ y < 0 or y >= stage.height: all_walkable = False break tid = stage.get_tile_at(x, y) if tid is None: pass elif tile_is_solid(tid): all_walkable = False if not all_walkable: break if not conflicts and all_walkable: # Make the new stockpile. stock = Stockpile(stage, (left, top, right - left + 1, bottom - top + 1), ['fish']) player_team.stockpiles.append(stock)
def get_item_at_pos(self, position): """L.get_item_at_pos (...) -> ListItem Gets the item at the passed position coordinates. """ eventarea = self.rect_to_client() if not eventarea.collidepoint(position): return None position = position[0] - eventarea.left, position[1] - eventarea.top border = base.GlobalStyle.get_border_size \ (self.__class__, self.style, StyleInformation.get ("ACTIVE_BORDER")) * 2 posy = self.vadjustment items = self.scrolledlist.items width = eventarea.width bottom = eventarea.bottom images = self.images spacing = self.scrolledlist.spacing for item in items: rect = Rect(images[item][1]) rect.y = posy rect.width = width + border if rect.bottom > bottom: rect.height = bottom - rect.bottom + border if rect.collidepoint(position): return item posy += images[item][1].height + spacing + border return None
def generate_fly_boss_level(gridsize): """Return a Level object for the fly boss level.""" level = Level((2, 15)) grid = Grid(gridsize) main_room = Rect(5, 5, 20, 20) for x, y, cell in grid: if not main_room.collidepoint(x, y): cell.append("wall") for x in range(1, 5): for y in range(14, 17): grid[x][y].remove("wall") for y in range(14, 17): grid[8][y].append("wall") grid[7][15].append("fly") grid[22][15].append("fly_wizard") __add_grid_to_level(level, grid) return level
class Button: """ Button class """ def __init__(self, screen, top, left, width, height, color=(255, 0, 0), text_color=(0, 0, 0), highlight_color=(0, 255, 0), value=0, text="", font_size=24): self._text = text self._value = value self._shape = Rect(top, left, width, height) self._screen = screen self._highlight_color = highlight_color self._color = color if not text: text = str(value) font = pygame.freetype.SysFont("Arial", font_size) # make the label a class variable, we don't care about the rect for now self._label, self._label_rect = font.render(text, text_color) self.redraw() def collidepoint(self, point): return self._shape.collidepoint(point) def get_text(self): return self._text def get_value(self): return self._value def get_rect(self): return self._shape def highlight(self): pygame.draw.rect(self._screen, self._highlight_color, self._shape) self._screen.blit(self._label, (self._shape.centerx - (self._label_rect.width / 2), self._shape.centery - (self._label_rect.height / 2))) def redraw(self): pygame.draw.rect(self._screen, self._color, self._shape) self._screen.blit(self._label, (self._shape.centerx - (self._label_rect.width / 2), self._shape.centery - (self._label_rect.height / 2))) def on_hover(self): self.highlight() def on_dehover(self): self.redraw()
def pick_rect(points, rects): ox, oy = sorted([(sum(p), p) for p in points])[0][1] x = ox y = oy ex = None while 1: x += 1 if not (x, y) in points: if ex is None: ex = x - 1 if ((ox, y + 1) in points): if x == ex + 1: y += 1 x = ox else: y -= 1 break else: if x <= ex: y -= 1 break c_rect = Rect(ox*tilewidth,oy*tileheight,\ (ex-ox+1)*tilewidth,(y-oy+1)*tileheight) rects.append(c_rect) rect = Rect(ox, oy, ex - ox + 1, y - oy + 1) kill = [p for p in points if rect.collidepoint(p)] [points.remove(i) for i in kill] if points: pick_rect(points, rects)
def IsBeingPointedAt(self): mouseCursorPosition = mouse.get_pos() rectangle = Rect(tuple(self.GetPosition()), tuple(self.GetDimensions())) return rectangle.collidepoint(mouseCursorPosition)
def on_mouse_down(pos, button): global current_poly global current_point if button == mouse.RIGHT: p = Poly() polys.append(p) set_current_poly(p) return if current_poly is not None: r = Rect(0, 0, 6, 6) for i, handle in enumerate(current_poly.handles): r.center = handle.pos if r.collidepoint(pos): current_point = i return for p in polys: if len(p) > 2 and p.contains(pos): set_current_poly(p) current_point = None return else: if current_poly is not None: current_poly.add_point(pos) current_point = len(current_poly) - 1
class CameraGroup(Group): def __init__(self): Group.__init__(self) self.x = 0 self.y = 0 self.upper_box = Rect(0, 0, 1000, 150) self.lower_box = Rect(0, 650, 1000, 150) self.left_box = Rect(0, 0, 150, 800) self.right_box = Rect(850, 0, 150, 800) self.camera_speed = 5 def draw_edges(self, root_node, surface, visited): if root_node.city_name in visited: return visited.add(root_node.city_name) for neighbor in root_node.neighbors: root_pos = root_node.rect.x + self.x, root_node.rect.y + self.y neighbor_pos = neighbor.rect.x + self.x, neighbor.rect.y + self.y pygame.draw.line(surface, WHITE, root_pos, neighbor_pos) self.draw_edges(neighbor, surface, visited) def draw(self, surface): # TODO(ted): the overridden draw() might have useful functionality that we're missing for sprite in self.sprites(): surface.blit(sprite.image, (sprite.rect.x + self.x, sprite.rect.y + self.y)) # TODO(ted): disentangle CameraGroup and this edge logic visited = set() self.draw_edges( next(s for s in self.sprites() if s.city_name == "Chicago"), surface, visited) def update(self, server_state, events): Group.update(self, server_state, events) if self.upper_box.collidepoint(pygame.mouse.get_pos()): self.y -= self.camera_speed if self.lower_box.collidepoint(pygame.mouse.get_pos()): self.y += self.camera_speed if self.left_box.collidepoint(pygame.mouse.get_pos()): self.x -= self.camera_speed if self.right_box.collidepoint(pygame.mouse.get_pos()): self.x += self.camera_speed
class PopUpMessage(BaseWidget): blinking = False ticks = 0 def __init__(self, text): super().__init__() self.layer = 50 self.image = Surface([200, 200]) self.rect = self.image.get_rect(center=(ANCHO // 2, (ALTO // 2) - 100)) self.image.fill(COLOR_AREA, [1, 1, self.rect.w - 2, self.rect.h - 2]) size = 14 f = self.crear_fuente(size) f2 = self.crear_fuente(20) success = False message = None while success is False: try: message = render_textrect(text, f, self.rect.inflate(-5, -3), COLOR_TEXTO, COLOR_AREA, 1) success = True except TextRectException: size -= 1 f = self.crear_fuente(size) msg_rect = message.get_rect(x=3, centery=self.rect.centery - self.rect.y) self.image.blit(message, msg_rect) self.blink_area = self.image.fill((100, 100, 100), [1, 1, self.rect.w - 31, 25]) self.write(' X ', f2, (200, 0, 0), right=self.rect.w - 2, y=1) self.close_area = Rect(367, self.rect.y, 32, 30) self.show() def on_mousebuttondown(self, event): if event.button == 1: if self.close_area.collidepoint(event.pos): self.hide() WidgetHandler.unlock() def blink(self): self.blinking = True def update(self): j = 8 if self.blinking: self.ticks += 1 t = self.ticks if (0 < t <= j) or (j * 2 + 1 <= t <= j * 3) or ( j * 4 + 1 <= t <= j * 5) or (j * 6 + 1 <= t <= j * 7): self.image.fill((200, 50, 0), self.blink_area) elif (j + 1 <= t <= j * 2) or (j * 3 + 1 <= t <= j * 4) or ( j * 5 + 1 <= t <= j * 6) or (j * 7 + 1 <= t <= j * 8): self.image.fill((255, 255, 0), self.blink_area) else: self.image.fill((100, 100, 100), self.blink_area) self.blinking = False self.ticks = 0
def click(self, pos): if Rect.collidepoint(self.rect, pos): x = pos[0] - 15 self.cur = x / self.total self.val = self.org * (self.cur / 0.5) self.config_anm() self.update_text() return ("{} = {:.3f}".format(self.pointer, self.val)) return 'False'
class Slider(Object): def __init__(self, topleft, size, color): super().__init__([ "mouse_down", "mouse_up", "mouse_motion", "value_changed", "value_stabilized" ]) self.connect("mouse_down", lambda event: self.clicked_handler(event)) self.connect("mouse_motion", lambda event: self.motion_handler(event)) self.connect("mouse_up", lambda _: self.mouse_up_handler()) self.volume = 0 self.color = color self.border_rect = Rect(topleft, size) self.moving = False self.ppv = self.border_rect.width // 100 def set_moving(self, state): self.moving = state def motion_handler(self, event): if self.moving: self.change_volume_by_pos(event.pos) def mouse_up_handler(self): if self.moving: self.set_moving(False) self.signal("value_stabilized", self.volume) def change_volume_by_pos(self, pos): self.set_volume((pos[0] - self.border_rect.x) // self.ppv) def clicked_handler(self, event): position = event.pos if self.border_rect.collidepoint(position): self.moving = True self.change_volume_by_pos(position) def set_volume(self, volume): self.volume = min(volume if volume >= 0 else 0, 100) self.signal("value_changed", self.volume) def add_volume(self, volume): self.set_volume(self.volume + volume) def draw(self, screen): volume_rect = self.border_rect.copy() volume_rect.width = self.ppv * self.volume pygame.draw.rect( screen, self.color, volume_rect, ) pygame.draw.rect(screen, (0, 0, 0), self.border_rect, 1)
def planets_in_rectangle(rect: pygame.Rect): """ Method return list of planets in given rectangle. """ all_planets = service.all_planet planet_in_rectangle = [ planet for planet in all_planets if rect.collidepoint(*planet.rect.center) ] return planet_in_rectangle
class Button: def __init__(self, screen, font, x, y, width, height, message): pygame.draw.rect(screen, BUTTON_COLOUR, [x, y, width, height]) button_text = font.render(message, False, BUTTON_TEXT_COLOUR) screen.blit(button_text, (x, y)) self.rect = Rect(x, y, width, height) def is_pressed(self, mouse_pos): if self.rect.collidepoint(mouse_pos): return True
def pt_within(p: set, r: Rect) -> bool: """ Check if point p is within rectangle r. Arguments: p - Point to check. r - Rectangle object. Returns: True if point within rectangle, False otherwise. """ return r.collidepoint(p)
def update(self, mousePos, mouseButtons, xPos, yPos, width = None): if width == None: clickArea = Rect(xPos, yPos, self.getWidth(), self.height) else: clickArea = Rect(xPos, yPos, width, self.height) if clickArea.collidepoint(mousePos) and mouseButtons[0] and not self.previousButtonStates[0]: if self.function!=None: self.function() else: print('Dropdown option: "%s" clicked'%self.label) self.previousButtonStates = mouseButtons
def getBoxAtPixel(self, mousex, mousey): #pygame.Rect has collidepoint() which checks if a given point is inside the rectangle #Approach 1 for i in range(self.board_width): for j in range(self.board_height): boxx, boxy = self.leftTopCoordsOfBox(i, j) #Create a rectangle solely to call collidePoint method rect = Rect(boxx, boxy, self.box_size, self.box_size) if rect.collidepoint(mousex, mousey): return (i, j) return (None, None)
def collide(self, position, rect): new_position = position + rect.center for point in self.get_locations(position, rect): layer = self.tile.map[point] if layer.is_collidable: x, y = Vector2(point) * self.tile.size rect = Rect(x, y, self.tile.size, self.tile.size) if (rect.collidepoint(new_position)): return True return False
class GameObjectManager(object): def __init__(self, width, height): self.rect = Rect(0, 0, width, height) def check_boundry(self): for prj in Projectile.projectiles: if not self.rect.collidepoint((prj.x, prj.y)): prj.remove = True for enemy in Enemy.enemies: if enemy.rect.collidepoint((prj.x, prj.y)): enemy.remove = True
def exp_collide_point(self, screen_pos, deg=None): """Return if `screen_pos` is in an expansion square.""" for d in (deg, ) if deg else self.expansion: center = self.deg2sp(d) n = self.deg2num_bullets[d] num_edge = math.ceil(math.sqrt(n)) length_edge = self.get_bullet_sep() * (num_edge + 1) size = Vector([length_edge, length_edge]) rect = Rect(myroundv(center - size / 2), myroundv(size)) if rect.collidepoint(*screen_pos): return d return None
def start_window(width, fps=60): pygame.init() win = pygame.display.set_mode((width, width)) clock = pygame.time.Clock() run = True chosen = ["human", "human"] while run: clock.tick(fps) human_button_1 = create_button(width // 5, width // 10, "Human", chosen[0] == "human") human_button_1_rect = Rect(width * 2 // 10, width * 4 // 10, width * 2 // 10, width // 10) ai_button_1 = create_button(width // 5, width // 10, "AI", chosen[0] == "ai") ai_button_1_rect = Rect(width * 2 // 10, width * 5 // 10, width * 2 // 10, width // 10) human_button_2 = create_button(width // 5, width // 10, "Human", chosen[1] == "human") human_button_2_rect = Rect(width * 6 // 10, width * 4 // 10, width * 2 // 10, width // 10) ai_button_2 = create_button(width // 5, width // 10, "AI", chosen[1] == "ai") ai_button_2_rect = Rect(width * 6 // 10, width * 5 // 10, width * 2 // 10, width // 10) network_button = create_button(width // 5, width // 10, "Network", chosen[1] == "network") network_button_rect = Rect(width * 4 // 10, width * 6 // 10, width * 2 // 10, width // 10) play_button = create_button(width * 4 // 10, width // 10, "Play") play_button_rect = Rect(width * 3 // 10, width * 8 // 10, width * 4 // 10, width // 10) win.blit(human_button_1, human_button_1_rect) win.blit(ai_button_1, ai_button_1_rect) win.blit(human_button_2, human_button_2_rect) win.blit(ai_button_2, ai_button_2_rect) win.blit(network_button, network_button_rect) win.blit(play_button, play_button_rect) draw_text(win, "V/S", width//20, (width//2, width*11//20), (255, 255, 0)) draw_text(win, "PyCarrom", width//10, (width//2, width*2//10)) draw_text(win, "Two Player Carrom Game", width//30, (width//2, width*3//10), (0, 0, 0)) draw_text(win, "Built on Python", width//30, (width//2, width*7//20), (0, 0, 0)) pygame.display.update() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() if event.type == pygame.MOUSEBUTTONDOWN: mouse_pos = pygame.mouse.get_pos() if human_button_1_rect.collidepoint(*mouse_pos): chosen[0] = "human" elif ai_button_1_rect.collidepoint(*mouse_pos): chosen[0] = "ai" if human_button_2_rect.collidepoint(*mouse_pos): chosen[1] = "human" elif ai_button_2_rect.collidepoint(*mouse_pos): chosen[1] = "ai" if network_button_rect.collidepoint(*mouse_pos): chosen[0]="network" chosen[1]="network" if play_button_rect.collidepoint(*mouse_pos): run = False return chosen
class Button(sprite.Sprite): ''' UI class. Used for do some button with function. ''' def __init__(self, x, y, w, h, function, texOnRelease, texOnPress, owner=None): self.owner = owner self.x = x self.y = y self.image = image.load(texOnRelease).convert() self.pressedImage = image.load(texOnPress).convert() self.rect = Rect(x, y, w, h) self.function = function self.currentImage = self.image self.visible = True if self.owner is not None: self.visible = self.owner.visible def update(self, click=None): if self.owner is not None: self.visible = self.owner.visible if not self.visible: return if click is not None: x, y = click.pos if self.rect.collidepoint(x, y): self.currentImage = self.pressedImage self.function() else: self.currentImage = self.image def draw(self, screen): if not self.visible: return screen.blit(self.currentImage, (self.rect.x, self.rect.y))
class NullWorld(object): """NullWorld is just a world with no obstacles or tiles. Multiple robots can be found.""" def __init__(self, length, width, robots): """Creates a new null world with a length, a width, and a list of robots Args: length: Length (will be converted to an int with floor) width: Width (will be converted to an int with floor) """ self.length = int(length) self.width = int(width) self.robots = {r.id: r for r in robots} self.hitbox = Rect(0, 0, self.width, self.length) def teleport(self, robot_id, x, y): """Safely teleports a robot a certain location. I.E, if another robot is occupying that space, it will be checked. System is probably not perfect as we tend to use `pygame.Rect` to approximate our hitbox. As long as the collision detection methods of `pygame.Rect` is implemented, we should be okay. Args: robot_id: The id of the robot from robot.id x: the x coordinate of the center of the robot after teleport y: the y coordinate of the center of the robot after teleport Returns: True if teleport is successful, False if not. Raises: KeyError if robot_id is not found """ if not self.hitbox.collidepoint(x, y): return False robot_to_be_moved = self.robots[robot_id] for robot in self.robots.values(): if robot_id == robot.id: continue if robot.hitbox.colliderect(robot_to_be_moved.hitbox): return False robot.hitbox.centerx = x robot.hitbox.centery = y return True
def handleInput(self, event): if event.type == MOUSEBUTTONDOWN: r = Rect(self.position, self.font.size(self.text)) if r.collidepoint(event.pos): self.capturing = True else: self.capturing = False if self.capturing: if event.type == KEYDOWN: if event.key == K_BACKSPACE: self.text = self.text[0:-1] if event.key <= 127 and not event.key == K_BACKSPACE: if event.mod & KMOD_SHIFT: self.text = self.text + chr(event.key).upper() else: self.text = self.text + chr(event.key)
def test_collidepoint(self): r = Rect(1, 2, 3, 4) self.failUnless(r.collidepoint(r.left, r.top), "r does not collide with point (left,top)") self.failIf(r.collidepoint(r.left - 1, r.top), "r collides with point (left-1,top)") self.failIf(r.collidepoint(r.left, r.top - 1), "r collides with point (left,top-1)") self.failIf(r.collidepoint(r.left - 1, r.top - 1), "r collides with point (left-1,top-1)") self.failUnless(r.collidepoint(r.right - 1, r.bottom - 1), "r does not collide with point (right-1,bottom-1)") self.failIf(r.collidepoint(r.right, r.bottom), "r collides with point (right,bottom)") self.failIf(r.collidepoint(r.right - 1, r.bottom), "r collides with point (right-1,bottom)") self.failIf(r.collidepoint(r.right, r.bottom - 1), "r collides with point (right,bottom-1)")
def get_monsters_in_line(self, x1, y1, x2, y2, radius): area = Rect(min(x1, x2) - radius, min(y1, y2) - radius, max(x1, x2) - min(x1, x2) + 2 * radius, max(y1, y2) - min(y1, y2) + 2 * radius) for monster in self.arena.creeps: if area.collidepoint((monster.x, monster.y)): try: dx, dy = x2 - x1, y2 - y1 slope = float(dy) / dx d_vert = monster.y - (slope * monster.x + (y1 - slope * x1)) slope = float(dx) / dy d_hori = monster.x - (slope * monster.y + (x1 - slope * y1)) dist = sqrt((d_hori*d_hori * d_vert*d_vert) / (d_hori*d_hori + d_vert*d_vert)) if dist < radius: yield monster except ZeroDivisionError: yield monster
def _channelfromdistance(self, location): screen = Rect(self._playfield.offset, self._playfield.dimensions) if screen.collidepoint(location[0:2]): dist = 0 else: if screen.left <= location[0] < screen.right: if location[1] < screen.top: dist = screen.top - location[1] else: dist = location[1] - screen.bottom elif screen.top <= location[1] < screen.bottom: if location[0] < screen.left: dist = screen.left - location[0] else: dist = location[0] - screen.left else: dist = min([sqrt(sum([(location[i]-p[i])**2 for i in range(2)])) for p in (screen.topleft, screen.bottomleft, screen.topright, screen.bottomright)]) dist /= 10 dist += abs(location[2]-self._playfield.level) return self._channels[min(len(self._channels)-1, int(dist))]
class Menu(object): """popup_menu.Menu Menu(pos, name, items) : return menu pos -> (x,y); topleft coordinates of the menu. name -> str; the name of the menu. items -> list; a list containing strings for menu items labels. This class is not intended to be used directly. Use PopupMenu or NonBlockingPopupMenu instead, unless designing your own subclass. """ def __init__(self, pos, name, items): screen = pygame.display.get_surface() screen_rect = screen.get_rect() self.name = name self.items = [] self.menu_item = None # Make the frame rect x,y = pos self.rect = Rect(x,y,0,0) self.rect.width += margin * 2 self.rect.height += margin * 2 # Make the title image and rect, and grow the frame rect self.title_image = font.render(name, True, text_color) self.title_rect = self.title_image.get_rect(topleft=(x+margin,y+margin)) self.rect.width = margin*2 + self.title_rect.width self.rect.height = margin + self.title_rect.height # Make the item highlight rect self.hi_rect = Rect(0,0,0,0) # Make menu items n = 0 for item in items: menu_item = MenuItem(item, n) self.items.append(menu_item) self.rect.width = max(self.rect.width, menu_item.rect.width+margin*2) self.rect.height += menu_item.rect.height + margin n += 1 self.rect.height += margin # Position menu fully within view if not screen_rect.contains(self.rect): savex,savey = self.rect.topleft self.rect.clamp_ip(screen_rect) self.title_rect.top = self.rect.top + margin self.title_rect.left = self.rect.left + margin # Position menu items within menu frame y = self.title_rect.bottom + margin for item in self.items: item.rect.x = self.rect.x + margin item.rect.y = y y = item.rect.bottom + margin item.rect.width = self.rect.width - margin*2 # Calculate highlight rect's left-alignment and size self.hi_rect.left = menu_item.rect.left self.hi_rect.width = self.rect.width - margin*2 self.hi_rect.height = menu_item.rect.height # Create the menu frame and highlight frame images self.bg_image = pygame.surface.Surface(self.rect.size) self.hi_image = pygame.surface.Surface(self.hi_rect.size) self.bg_image.fill(bg_color) self.hi_image.fill(hi_color) # Draw menu border rect = self.bg_image.get_rect() pygame.draw.rect(self.bg_image, glint_color, rect, 1) t,l,b,r = rect.top,rect.left,rect.bottom,rect.right pygame.draw.line(self.bg_image, shadow_color, (l,b-1), (r,b-1), 1) pygame.draw.line(self.bg_image, shadow_color, (r-1,t), (r-1,b), 1) # Draw title divider in menu frame left = margin right = self.rect.width - margin*2 y = self.title_rect.height + 1 pygame.draw.line(self.bg_image, shadow_color, (left,y), (right,y)) def draw(self): # Draw the menu on the main display. screen = pygame.display.get_surface() screen.blit(self.bg_image, self.rect) screen.blit(self.title_image, self.title_rect) for item in self.items: if item is self.menu_item: self.hi_rect.top = item.rect.top screen.blit(self.hi_image, self.hi_rect) screen.blit(item.image, item.rect) def check_collision(self, mouse_pos): # Set self.menu_item if the mouse is hovering over one. self.menu_item = None if self.rect.collidepoint(mouse_pos): for item in self.items: if item.rect.collidepoint(mouse_pos): self.menu_item = item break
class Element: def __init__(self, rect = None, layer=0, visible=True, active=True): if rect is not None: self.rect = rect else: self.rect = Rect((0, 0), (0, 0)) self.old_active = None self.old_visible = None self.old_rect = None self.layer = layer self.visible = visible self.active = active self.dirty_list = [] return def draw(self, screen): return def update(self): def rects_are_synchronized(): r = self.rect o = self.old_rect return (r.x, r.y, r.size) == (o.x, o.y, o.size) if self.old_rect is None: self.dirty_list.append(self.rect.inflate(5, 5)) self.old_rect = Rect((self.rect.x, self.rect.y), (self.rect.w, self.rect.h)) elif not rects_are_synchronized(): self.refresh() self.old_rect = Rect((self.rect.x, self.rect.y), (self.rect.w, self.rect.h)) self.update_active_and_visible() self.remove_duplicate_dirty_rects() return def remove_duplicate_dirty_rects(self): unique_list = [] for dirty_rect in self.dirty_list: if not dirty_rect in unique_list: unique_list.append(dirty_rect) self.dirty_list = unique_list return def update_active_and_visible(self): if self.old_visible is None or self.old_visible != self.visible \ or self.old_active is None or self.old_active != self.active: self.refresh() self.old_active = self.active self.old_visible = self.visible return def refresh(self): if self.old_rect is not None: self.dirty_list.append(self.old_rect.inflate(5, 5)) self.dirty_list.append(self.rect.inflate(5, 5)) return def suspend(self): self.active = False self.visible = False return def restore(self): self.active = True self.visible = True return def decorated_element(self): return self def is_mouse_over(self): return self.visible and self.rect.collidepoint(mouse_position()) def is_mouse_clicking(self): return self.visible and is_left_mouse_clicked() and self.is_mouse_over()
class Maze: SOLID = 0 EMPTY = 1 SEEN = 2 GOAL = 3 def __init__(self, seed, width, height): # use the seed given to us to make a pseudo-random number generator # we will use that to generate the maze, so that other players can # generate the exact same maze given the same seed. print "Generating maze:%d,%d,%d" % (seed, width, height) self.seed = seed self.generator = random.Random(seed) self.width, self.height = width, height self.map = [] self.bounds = Rect(0,0,width,height) for x in range(0, width): self.map.append([self.SOLID] * self.height) startx = self.generator.randrange(1,width,2) starty = self.generator.randrange(1,height,2) self.dig(startx,starty) def validMove(self, x, y): return self.bounds.collidepoint(x,y) and self.map[x][y]!=self.SOLID def validDig(self, x, y): return self.bounds.collidepoint(x,y) and self.map[x][y]==self.SOLID def validDigDirections(self, x, y): directions = [] if self.validDig(x,y-2): directions.append((0,-1)) if self.validDig(x+2,y): directions.append((1,0)) if self.validDig(x,y+2): directions.append((0,1)) if self.validDig(x-2,y): directions.append((-1,0)) return directions def fill(self, color): for y in range(0, height): for x in range(0, width): self.map[x][y] = color def digRecursively(self, x, y): """This works great, except for python's lame limit on recursion depth.""" self.map[x][y] = self.EMPTY directions = self.validDigDirections(x,y) while len(directions) > 0: direction = self.generator.choice(directions) self.map[x+direction[0]][y+direction[1]] = self.EMPTY self.dig(x+direction[0]*2, y+direction[1]*2) directions = self.validDigDirections(x,y) def dig(self, x, y): stack = [(x,y)] while len(stack) > 0: x, y = stack[-1] self.map[x][y] = self.EMPTY directions = self.validDigDirections(x,y) if len(directions) > 0: direction = self.generator.choice(directions) self.map[x+direction[0]][y+direction[1]] = self.EMPTY stack.append((x+direction[0]*2, y+direction[1]*2)) else: stack.pop()
tolerance = 1 if r1.width < tolerance: r1.width = tolerance if r1.height < tolerance: r1.height = tolerance if r2.width < tolerance: r2.width = tolerance if r2.height < tolerance: r2.height = tolerance for point in p: try: res1 = r1.collidepoint(point) res2 = r2.collidepoint(point) if res1 and res2: point = [int(pp) for pp in point] return point except: # sometimes the value in a point are too large for PyGame's Rect class str = "point was invalid ", point print str # This is the case where the infinately long lines crossed but # the line segments didn't return None else: return None
def collidepoint(self, other): other = rotate_point(other, -self.angle, self.center) return Rect.collidepoint(self, other)
class Camera: def __init__(self, screen, screensize, playerpos, tileImage, tileSize, currentWeapon): self.screen = screen self.screensize = screensize self.playerx,self.playery = playerpos self.halfscreenx,self.halfscreeny = screensize self.halfscreenx /= 2 self.halfscreeny /= 2 self.rect = Rect(self.playerx-self.halfscreenx, self.playery-self.halfscreeny, self.halfscreenx * 2, self.halfscreeny * 2) self.tiledImage = tileImage self.tileSize = tileSize self.dpx = 0 self.dpy = 0 self.currentWeapon = currentWeapon self.goreObjects = [] def setCurrentWeapon(self, cw): self.currentWeapon = cw def registerGore(self, go): self.goreObjects.append(go) def update(self, playerx, playery, dt): self.dpx += self.playerx - playerx self.dpy += self.playery - playery self.playerx = playerx self.playery = playery self.rect.top = playery - self.halfscreeny self.rect.left = playerx - self.halfscreenx if self.tiledImage != None: r = self.screen.get_rect() rect = Rect(r.top - 2 * self.tileSize, r.left - 2 * self.tileSize, r.width + 2 * self.tileSize, r.height + 2 * self.tileSize) rect.centerx += self.dpx rect.centery += self.dpy self.tiledImage.draw(self.screen, rect) toRemove = [] for i,gore in enumerate(self.goreObjects): x = gore.getX() - self.rect.left y = gore.getY() - self.rect.top self.screen.blit(gore.getScreen(), (x,y)) if gore.update(dt): toRemove.append(i) for i in toRemove: del self.goreObjects[i] self.screen.blit(self.currentWeapon, (15,15)) def drawList(self, objList, img1, img2): toRemove = [] for i in range(len(objList)): if not self.rect.colliderect(objList[i].getRect()): toRemove.append(i) continue relposx = objList[i].getX() - self.rect.left relposy = objList[i].getY() - self.rect.top timer = objList[i].getInviTimer() if (timer>150): if math.sqrt(math.pow((int(relposx)-self.halfscreenx),2) + math.pow((int(relposy)-self.halfscreeny),2))>100: self.screen.blit(img1, (int(relposx),int(relposy))) else: self.screen.blit(img2, (int(relposx),int(relposy))) for i in reversed(toRemove): objList.pop(i) def drawPlayer(self, playerimage, Score): self.screen.blit(playerimage, (self.halfscreenx,self.halfscreeny)) font = pygame.font.Font(None, 30) self.screen.blit(font.render(str(Score), 1, (0,0,0)), (25,25)) def drawObj(self, obj, img): if not self.rect.colliderect(obj.getRect()): return relposx = obj.getX() relposy = obj.getY() self.screen.blit(img, (relposx,relposy)) def drawBulletList(self, objList): toRemove = [] for i in range(len(objList)): if not self.rect.collidepoint(objList[i].getX(), objList[i].getY()): toRemove.append(i) continue relposx = objList[i].getX() - self.rect.left relposy = objList[i].getY() - self.rect.top self.screen.blit(objList[i].getImage(), (int(relposx), int(relposy))) #pygame.draw.circle(self.screen, (0,0,0), (int(relposx), int(relposy)), 5) for i in reversed(toRemove): del objList[i]
class MenuItem(Rect): def __init__(self, Rec, Ident, Text, Action, RColor, OColor, TColor, Image, Toggle): self.rect = Rect(Rec) self.ident = Ident self.images = [Surface((self.rect.w, self.rect.h)), Surface((self.rect.w, self.rect.h))] self.toggle = Toggle if self.toggle: self.toggledOn = False self.changed = False if isinstance(Action, list): self.action = Action else: self.action = [Action] self.display = Display(self, self.images[0], self.images[0], False) self.rcolor = RColor self.ocolor = OColor self.tcolor = TColor self.text = Text self.image = Image self.update() def update(self, Rect=None, RColor=None, OColor=None, Text=None, TColor=None, Image=None): if Rect == None: Rect = self.rect if RColor == None: RColor = self.rcolor if OColor == None: OColor = self.ocolor if Text == None: Text = self.text if TColor == None: TColor = self.tcolor if Image == None: Image = self.image colors = [RColor, OColor] for i in range(len(colors)): self.images[i].fill(colors[i]) if Text: if main.android: text = pygame.surface.Surface((0, 0)) else: text = pygame.font.Font(None, 25).render(Text, 1, TColor) self.images[i].blit(text, ((self.images[i].get_width() / 2) - (text.get_width() / 2), (self.images[i].get_height() / 2) - (text.get_height() / 2))) if Image != False: self.images[i].blit(Image, (1, 1)) def move(self, vect): self.rect.x += self.vect[0] self.rect.y += self.vect[1] def grow(self, dx, dy): self.rect.w += dx self.rect.h += dy def tick(self, input, menu, mPos): self.changed = False try: collide = self.rect.collidepoint(mPos) # Fix this, stop the error rather than ignoring it except: return None if self.toggle and self.toggledOn: self.display.image = self.images[1] else: self.display.image = self.images[collide] if collide and input is MOUSEBUTTONDOWN: if self.toggle: self.toggledOn = True self.changed = True return self.ident
class Menu: # Konstuktor inicializuje premenne. def __init__(self, pygameWindow,gameVariable,images): # bool hodnoty self.notOver = True self.startGame = False self.closeGame = False self.loadGame = False self.gameVariable = gameVariable # okno self.window = pygameWindow self.images = images #velkosti self.rectWidth = pygameWindow.get_width() / 3 self.rectHeight = pygameWindow.get_height() / 10 self.rectX = (pygameWindow.get_width() / 2) - (self.rectWidth / 2) # Rect(top,left, width, height) self.nazovHryRect = Rect(0,0,self.window.get_width(),pygameWindow.get_height()/3) self.newGameRect = Rect(self.rectX, 150, self.rectWidth, self.rectHeight) self.loadGameRect = Rect(self.rectX, 250, self.rectWidth, self.rectHeight) self.exitRect = Rect(self.rectX, 350, self.rectWidth, self.rectHeight) # font a texty font.init() self.font = font.SysFont("norasi",int(self.rectHeight/2)) #iniclializacia lablov self._initLabel() # Metoda zobrazi menu a spusti loop. def showMenu(self): self.clock = time.Clock() self.FPS = 30 # DORIESIT SPUSTENIE while self.notOver: self.window.fill(Color.white) draw.rect(self.window, Color.blue, self.newGameRect) draw.rect(self.window,Color.green,self.loadGameRect) draw.rect(self.window, Color.red, self.exitRect) self._checkClick() self._showLabel() display.update() self.clock.tick(self.FPS) #overi klik def _checkClick(self): for actualEvent in event.get(): if actualEvent.type == QUIT: quit() sys.exit() # overenie kliknutia, ak klikol overim, ci klikol na tlacidlo if actualEvent.type == MOUSEBUTTONUP: position = mouse.get_pos() self._checkIfInButton(position) def _checkIfInButton(self, position): # overenie new game tlacidla if self.newGameRect.collidepoint(position): self.gameVariable.newGame() self.notOver = False #load game tlacidlo elif self.loadGameRect.collidepoint(position): self.gameVariable.loadGame() self.notOver = False #exit game tlacidlo elif self.exitRect.collidepoint(position): quit() sys.exit() # inicializuje texty pre buttoni def _initLabel(self): textStart = "New Game" textExit = "Exit" gameName = "Unix-Semestralka HRA" textLoad = "Load Game" win = "Gratulujem, PREZIL SI!!" lose = "PREHRAL SI!" labelNewGame = self.font.render(textStart,1,Color.black) labelLoadGame = self.font.render(textLoad,1,Color.black) labelExit = self.font.render(textExit,1,Color.black) novyFont = font.SysFont("arial",50) labelHra = novyFont.render(gameName,1,Color.red) self.labelWin = novyFont.render(win,1,Color.red) self.labelLose = novyFont.render(lose,1,Color.red) self.buttons = [(self.newGameRect,labelNewGame), (self.loadGameRect,labelLoadGame), (self.exitRect,labelExit), (self.nazovHryRect,labelHra)] def _showLabel(self): for button,label in self.buttons: x = (button.width - label.get_width())/2 y = (button.height - label.get_height())/2 self.window.blit(label,(button.x + x,button.y + y)) def showWin(self): x = (self.window.get_width() - self.labelWin.get_width()) / 2 y = (self.window.get_height() - self.labelWin.get_height()) / 2 while True: self.window.fill(Color.white) for actualEvent in event.get(): if actualEvent.type == QUIT: quit() sys.exit() self.window.blit(self.labelWin,(x,y)) display.update() def showLose(self): x = (self.window.get_width() - self.labelLose.get_width()) / 2 y = (self.window.get_height() - self.labelLose.get_height()) / 2 while True: self.window.fill(Color.white) for actualEvent in event.get(): if actualEvent.type == QUIT: quit() sys.exit() self.window.blit(self.labelLose,(x,y)) display.update() def showTutorial(self): notEnd = True while notEnd: self.window.blit(self.images.tutorial,(0,0)) for actualEvent in event.get(): if actualEvent.type == QUIT: quit() sys.exit() elif actualEvent.type == pygame.KEYDOWN: # check for key presses if actualEvent.key == pygame.K_KP_ENTER or actualEvent.key == pygame.K_SPACE: print("enter") notEnd = False display.update()
def intersection_pt(p1, p2, p3, p4): p = getIntersectPoint(p1, p2, p3, p4) if p is not None: width = p2[0] - p1[0] height = p2[1] - p1[1] r1 = Rect(p1, (width , height)) r1.normalize() width = p4[0] - p3[0] height = p4[1] - p3[1] r2 = Rect(p3, (width, height)) r2.normalize() # Ensure both rects have a width and height of at least 'tolerance' else the # collidepoint check of the Rect class will fail as it doesn't include the bottom # and right hand side 'pixels' of the rectangle tolerance = 1 if r1.width <tolerance: r1.width = tolerance if r1.height <tolerance: r1.height = tolerance if r2.width <tolerance: r2.width = tolerance if r2.height <tolerance: r2.height = tolerance for point in p: try: res1 = r1.collidepoint(point) res2 = r2.collidepoint(point) if res1 and res2: point = [int(pp) for pp in point] return point except: # sometimes the value in a point are too large for PyGame's Rect class str = "point was invalid ", point print str # This is the case where the infinately long lines crossed but # the line segments didn't return None else: return None # # Test script below... # if __name__ == "__main__": # # line 1 and 2 cross, 1 and 3 don't but would if extended, 2 and 3 are parallel # # line 5 is horizontal, line 4 is vertical # p1 = (1,5) # p2 = (4,7) # p3 = (4,5) # p4 = (3,7) # p5 = (4,1) # p6 = (3,3) # p7 = (3,1) # p8 = (3,10) # p9 = (0,6) # p10 = (5,6) # p11 = (472.0, 116.0) # p12 = (542.0, 116.0) # assert None != calculateIntersectPoint(p1, p2, p3, p4), "line 1 line 2 should intersect" # assert None != calculateIntersectPoint(p3, p4, p1, p2), "line 2 line 1 should intersect" # assert None == calculateIntersectPoint(p1, p2, p5, p6), "line 1 line 3 shouldn't intersect" # assert None == calculateIntersectPoint(p3, p4, p5, p6), "line 2 line 3 shouldn't intersect" # assert None != calculateIntersectPoint(p1, p2, p7, p8), "line 1 line 4 should intersect" # assert None != calculateIntersectPoint(p7, p8, p1, p2), "line 4 line 1 should intersect" # assert None != calculateIntersectPoint(p1, p2, p9, p10), "line 1 line 5 should intersect" # assert None != calculateIntersectPoint(p9, p10, p1, p2), "line 5 line 1 should intersect" # assert None != calculateIntersectPoint(p7, p8, p9, p10), "line 4 line 5 should intersect" # assert None != calculateIntersectPoint(p9, p10, p7, p8), "line 5 line 4 should intersect" # print "\nSUCCESS! All asserts passed for doLinesIntersect"
class MapBase(Window): def __init__(self, width, height, default_tile_name='floor'): Window.__init__(self,None,10) self.save_data = SaveObject() self.tile_manager = TileManager() default_tile = self.tile_manager.get_tile(default_tile_name) self.tiles = [] for x in range(width): col = [] self.tiles.append(col) for y in range(height): location = MapLocation(self, (x,y), default_tile) col.append(location) self.width = width self.height = height tiles_x = core.screen.get_width() / 32 tiles_y = core.screen.get_height() / 32 self.dimentions = Rect(0,0,width,height) self.character = None self.entities = RenderEntity() self.non_passable_entities = RenderEntity() self.viewport = Rect(0,0,tiles_x,tiles_y) self.offset = Rect(0,0,0,0) self.map_tile_coverage = Rect(0,0,tiles_x+5,tiles_y+5) if self.map_tile_coverage.width > width: self.map_tile_coverage.width = width if self.map_tile_coverage.height > height: self.map_tile_coverage.height = height self.map_non_scroll_region = \ self.viewport.inflate(SCROLL_EDGE*-2,SCROLL_EDGE*-2) self.action_listeners = {} self.entry_listeners = {} self.movement_listeners = [] self.scrolling = False self.frame = 0 self.map_frames_dirty = [True,True,True,True] self.map_frames = [] self.heal_points = 0 self.regen_rate = 2000000000 self.sound = core.mixer.Sound('%s/sounds/beep.wav' % DATA_DIR) for f in range(4): #TODO Add non hardcoded values for buffer #TODO Make sure we don't make a larger surface than we need #TODO Ex: 5x5 map self.map_frames.append(Surface(((1+width) * TILE_SIZE, \ (1+height) * TILE_SIZE))) def __getstate__(self): dict = {} dict['width'] = self.width dict['height'] = self.height dict['offset.width'] = self.offset.width dict['offset.height'] = self.offset.height dict['save_data'] = self.save_data return dict def __setstate__(self, dict): if self.__class__.__name__ == 'MapBase': self.__init__(dict['width'],dict['height']) else: self.__init__() self.save_data = dict['save_data'] self.offset.width = dict['offset.width'] self.offset.height = dict['offset.height'] self.blur_events() def dispose(self): self.destroy() del self.tiles self.tile_manager.clear() del self.action_listeners del self.entry_listeners del self.movement_listeners self.entities.empty() self.non_passable_entities.empty() self.character.map = None def set_regen_rate(self, rate): self.regen_rate = rate def get(self, x, y): if x<0 or y<0: return None try: return self.tiles[x][y] except: return None def calculate_tile_coverage(self, viewable): if self.character is None: return coverage = self.map_tile_coverage coverage.center = self.character.pos view_scroll = viewable.inflate(8,8) coverage.clamp_ip(view_scroll) coverage.clamp_ip(self.dimentions) self.offset.left = (viewable.left - coverage.left) * TILE_SIZE self.offset.top = (viewable.top - coverage.top ) * TILE_SIZE if not self.map_non_scroll_region.collidepoint(self.character.pos): self.map_non_scroll_region = \ self.viewport.inflate(SCROLL_EDGE*-2,SCROLL_EDGE*-2) def set_location(self, loc, tile_name, walkable=True, tile_pos=None): x, y = loc location = self.get(x, y) tile = self.tile_manager.get_tile(tile_name, None, tile_pos) location.set_tile(tile) location.set_walkable(walkable) def place_character(self, character, pos, passable=False, direction=NORTH): self.character = character character.map = self character.can_trigger_actions = 1 if not self.viewport.collidepoint(pos): self.viewport.center = pos self.viewport.clamp_ip(self.dimentions) self.place_entity(character, pos, passable, direction) self.calculate_tile_coverage(self.viewport) def place_entity(self, entity, entity_pos, passable=False, direction=NORTH): entity.face(direction) entity.map = self entity.move_to(entity_pos) self.entities.add(entity) if not passable: self.non_passable_entities.add(entity) def add_entry_listener(self, x, y, listener): self.entry_listeners[ (x,y) ] = listener def add_movement_listener(self, listener): self.movement_listeners.append(listener) def update(self): """Invoked once per cycle of the event loop, to allow animation to update""" if self.character.entered_tile: self.character.entered_tile = False self.check_heal() if self.entry_listeners.has_key( self.character.pos ): self.entry_listeners[self.character.pos]() for listener in self.movement_listeners: listener() if self.scrolling: axis = self.scroll_axis diff = [0,0] diff[axis] = self.scroll_anchor - self.character.rect[axis] self.entities.scroll(diff) diff[axis] = diff[axis] * -1 self.offset[axis] = self.offset[axis] + diff[axis] if not self.character.moving: self.scrolling = False if self.is_left(): self.move_character(WEST) if self.is_right(): self.move_character(EAST) if self.is_up(): self.move_character(NORTH) if self.is_down(): self.move_character(SOUTH) if self.map_frames_dirty[self.frame]: self.build_current_frame() self.map_frames_dirty[self.frame] = False self.entities.update() def draw(self, blit): blit(self.map_frames[self.frame], (0,0), self.offset) self.entities.draw(blit) def build_current_frame(self): #TODO Decide if map_tile_coverage is the right name for this blit = self.map_frames[self.frame].blit rect = (self.frame * TILE_SIZE, 0, TILE_SIZE, TILE_SIZE) x = 0 y = 0 for col in range(self.map_tile_coverage.left, \ self.map_tile_coverage.right): column = self.tiles[col] for row in range(self.map_tile_coverage.top, \ self.map_tile_coverage.bottom): blit(column[row].tile, (x,y), rect) y = y + TILE_SIZE x = x + TILE_SIZE y = 0 def init(self): self.offset.width = core.screen.get_rect().width self.offset.height = core.screen.get_rect().height self.entities.run_command('enter_map') def handle_event(self,event): if event.type == PUSH_ACTION_EVENT: self.character_activate() if event.type == PUSH_ACTION2_EVENT: menu.run_main_menu() if event.type == QUIT_EVENT: core.wm.running = False def check_heal(self): self.heal_points = self.heal_points + 1 if self.heal_points >= self.regen_rate: core.game.save_data.hero.regenerate() self.heal_points = 0 def character_activate(self): if not self.character.moving: target = add(self.character.pos,MOVE_VECTORS[self.character.facing]) entities = self.non_passable_entities.entity_collisions(target) for e in entities: e.activate() def move_character(self, dir): self.character.move(dir) if not self.scrolling: if self.character.moving: nsr = self.map_non_scroll_region x,y = self.character.pos if dir % 2 == 0: # North or south if y < nsr.bottom and \ y >= nsr.top: return if y < SCROLL_EDGE or \ y >= self.height - SCROLL_EDGE: return self.scroll_axis = 1 else: # East or west if x < nsr.right and \ x >= nsr.left: return if x < SCROLL_EDGE or \ x >= self.width - SCROLL_EDGE: return self.scroll_axis = 0 self.scrolling = True vector = MOVE_VECTORS[dir] self.map_non_scroll_region.move_ip(vector) old_viewport = self.viewport self.viewport = old_viewport.move(vector) self.scroll_anchor = self.character.rect[self.scroll_axis] if not self.map_tile_coverage.contains(self.viewport): self.calculate_tile_coverage(old_viewport) self.dirty() def dirty(self): for f in range(4): self.map_frames_dirty[f] = True def move_ok(self, target_pos, character): x, y = target_pos target = self.get(x,y) if target is not None and target.is_walkable(): entities = self.non_passable_entities.entity_collisions(target_pos) if len(entities) > 0: if character.can_trigger_actions: for e in entities: e.touch() else: for e in entities: if e.can_trigger_actions: character.touch() return 0 else: self.sound.play() return 1 else: return 0 def get_tiles_from_ascii(self,ascii,tile_map): for y in range(self.height): line = ascii[y] for x in range(self.width): c = line[x] args = tile_map[c] pos = None if len(args) > 1: pos = args[1] self.set_location( (x,y), args[0], tile_map['walkable'].find(c)!=-1, pos )
class PaletteView(GridView): # nrows int No. of displayed rows # ncols int No. of displayed columns # # Abstract methods: # # num_items() --> no. of items # draw_item(surface, item_no, rect) # click_item(item_no, event) # item_is_selected(item_no) --> bool # sel_color = (0, 128, 255) # sel_width = 2 # scroll_button_size = 16 # scroll_button_color = (0, 128, 255) sel_color = ThemeProperty('sel_color') sel_width = ThemeProperty('sel_width') scroll_button_size = ThemeProperty('scroll_button_size') scroll_button_color = ThemeProperty('scroll_button_color') highlight_style = 'frame' # or 'fill' def __init__(self, cell_size, nrows, ncols, scrolling = False): GridView.__init__(self, cell_size, nrows, ncols) self.nrows = nrows self.ncols = ncols self.scrolling = scrolling if scrolling: d = self.scroll_button_size l = self.rect.width b = self.rect.height self.rect.width += d self.scroll_up_rect = Rect(l, 0, d, d).inflate(-4, -4) self.scroll_down_rect = Rect(l, b - d, d, d).inflate(-4, -4) self.scroll = 0 def draw(self, surface): GridView.draw(self, surface) if self.can_scroll_up(): self.draw_scroll_up_button(surface) if self.can_scroll_down(): self.draw_scroll_down_button(surface) def draw_scroll_up_button(self, surface): r = self.scroll_up_rect c = self.scroll_button_color draw.polygon(surface, c, [r.bottomleft, r.midtop, r.bottomright]) def draw_scroll_down_button(self, surface): r = self.scroll_down_rect c = self.scroll_button_color draw.polygon(surface, c, [r.topleft, r.midbottom, r.topright]) def draw_cell(self, surface, row, col, rect): i = self.cell_to_item_no(row, col) if i is not None: highlight = self.item_is_selected(i) self.draw_item_and_highlight(surface, i, rect, highlight) def draw_item_and_highlight(self, surface, i, rect, highlight): if highlight: self.draw_prehighlight(surface, i, rect) self.draw_item(surface, i, rect) if highlight: self.draw_posthighlight(surface, i, rect) def draw_prehighlight(self, surface, i, rect): if self.highlight_style == 'frame': frame_rect(surface, self.sel_color, rect, self.sel_width) else: surface.fill(self.sel_color, rect) def draw_posthighlight(self, surface, i, rect): pass def mouse_down(self, event): if self.scrolling: p = event.local if self.scroll_up_rect.collidepoint(p): self.scroll_up() return elif self.scroll_down_rect.collidepoint(p): self.scroll_down() return GridView.mouse_down(self, event) def scroll_up(self): if self.can_scroll_up(): self.scroll -= self.page_size() def scroll_down(self): if self.can_scroll_down(): self.scroll += self.page_size() def can_scroll_up(self): return self.scrolling and self.scroll > 0 def can_scroll_down(self): return self.scrolling and self.scroll + self.page_size() < self.num_items() def page_size(self): return self.nrows * self.ncols def click_cell(self, row, col, event): i = self.cell_to_item_no(row, col) if i is not None: self.click_item(i, event) def cell_to_item_no(self, row, col): i = self.scroll + row * self.num_cols() + col if 0 <= i < self.num_items(): return i else: return None def num_rows(self): return self.nrows def num_cols(self): return self.ncols
class WindowUser(Window): """super class for WindowInput and WindowConfirm""" def __init__(self, contents_w, contents_h): #center the window on the screen screen = pygame.display.get_surface() screen_w, screen_h = screen.get_size() w, h = contents_w+32, contents_h+32 x = (screen_w - w)//2 y = (screen_h - h)//2 Window.__init__(self, x, y, w, h) self.windowskin = load_windowskin('editor.png') self.create_contents() self.contents.fill((0,0,0,0)) self.cancel_allowed = True def create_valid_cancel(self): "create Valid and Cancel buttons" width, height = self.contents_size self.valider = Surface((100, 26)) valider = self.font.render("Valider", 1, (0,0,0)) w, h = valider.get_size() self.valider.fill((35, 131, 56)) pygame.draw.lines(self.valider, (0,0,0), 0, [(0,25),(99,25),(99,0)]) self.valider.blit(valider, ((100-w)//2, (32-h)//2)) self.annuler = Surface((100, 26)) annuler = self.font.render("Annuler", 1, (0,0,0)) w, h = annuler.get_size() self.annuler.fill((255, 60, 83)) pygame.draw.lines(self.annuler, (0,0,0), 0, [(0,25),(99,25),(99,0)]) self.annuler.blit(annuler, ((100-w)//2, (32-h)//2)) self.annuler_rect = Rect(10, height-32, 100, 26) self.valider_rect = Rect(width-100-10, height-32, 100, 26) self.contents.blit(self.annuler, self.annuler_rect) self.contents.blit(self.valider, self.valider_rect) @property def offsettext(self): return 10 @property def margintext(self): return 2 def check_valid(self, event): if event.type == pygame.KEYDOWN and\ event.key == pygame.K_RETURN: return True #get Cancel elif event.type == pygame.MOUSEBUTTONDOWN and\ event.button == 1: rel_pos = (event.pos[0]-self.rect.x-self.offset, event.pos[1]-self.rect.y-self.offset) if self.valider_rect.collidepoint(rel_pos): #Cancel and return return True def check_cancel(self, event): if event.type == pygame.QUIT: pygame.event.post(event) return True elif self.cancel_allowed: if event.type == pygame.KEYDOWN and\ event.key == pygame.K_ESCAPE: return True #get Cancel elif event.type == pygame.MOUSEBUTTONDOWN and\ event.button == 1: rel_pos = (event.pos[0]-self.rect.x-self.offset, event.pos[1]-self.rect.y-self.offset) if self.annuler_rect.collidepoint(rel_pos): #Cancel and return return True return False def update(self, event): if self.check_cancel(event): return False elif self.check_valid(event): return True for widget in self.widgets: widget.update(event) return None
class Element(object): """ The Element object is the abstract class that all gui elements of nostalgia inherit from. It has the basic definitions and variables needed by the by the Console object to hand events and rendering. for child in self.children: child.stylize() style = theme.current.get_dict(self) for key, val in style.iteritems(): kvc.set_value_for_keypath(self, key, val) self.layout() """ def __init__(self, x, y, width, height, color=Color(0, 0, 0, 0)): super(Element, self).__init__() self.frame = Rect(x, y, width, height) self.surface = Surface(self.size(), SRCALPHA) self.color = color if self.color is not None: self.surface.fill(self.color) self.parent = None self.on_mouse_up = Signal() self.on_mouse_down = Signal() self.on_mouse_drag = Signal() self.draggable = False self.enabled = True self.hidden = False def size(self): """Returns size of element.""" return self.frame.size def hit(self, mouse_pos): if self.hidden or not self.enabled: return None if not self.frame.collidepoint(mouse_pos): return None else: return self def position(self): """Returns position of the element.""" return self.frame.x, self.frame.y def render(self, window): """ The render definition takes a surface as an argument and blits its surface to the one given. """ if not self.hidden: window.blit(self.surface, self.position()) def set_parent(self, parent): """ Sets the master handler of this object. Master's can be panels or the main console window. This updates this objects position in a way that makes the origin (0, 0) that of its masters (x, y) position. It takes the master object as an argument. """ self.parent = parent self.update_position() def update_position(self): """ The method updatePosition, sets this objects position based upon its masters position. See the setMaster definition for a more thorough explanation. """ if hasattr(self.parent, 'frame'): x = self.frame.x + self.parent.frame.x y = self.frame.y + self.parent.frame.y self.frame.x, self.frame.y = x, y def mouse_up(self, button, point): self.on_mouse_up(self, button, point) def mouse_down(self, button, point): self.on_mouse_down(self, button, point) def mouse_drag(self, view, position, event): self.on_mouse_drag(self, position, event)
def __contains__(self, event): r = Rect(self._rect) r.left = 0 r.top = 0 p = self.global_to_local(event.pos) return r.collidepoint(p)
class Slider(Widget): def __init__(self, position, minval, maxval, defaultval, sSurface, rSurface): """A class for a click-n-dragable slider widget. Intended for integers. position - A pair (x,y) describing the upper-left corner of the slider minval - The minimum value the slider can set maxval - The maximum value the slider can set defaultval - The default value of the slider sSurface - The surface to be rendered for the click-n-drag slider itself rSurface - The surface to be rendered representing the bounds of slider""" p = Rect(position, (rSurface.get_rect().width, sSurface.get_rect().height)) Widget.__init__(self, p) self.currentval = defaultval self.minval = minval self.maxval = maxval self.sSurface = sSurface sliderx = ( ((self.currentval - self.minval) * self.position.width) / (self.maxval - self.minval) ) - self.sSurface.get_width() / 2 self.sliderpos = Rect( (sliderx + self.position.x, self.position.y), (self.sSurface.get_width(), self.sSurface.get_height()) ) self.rSurface = rSurface self.moveAction = False def handleInput(self, event): if event.type == MOUSEBUTTONDOWN: if self.sliderpos.collidepoint(event.pos): self.moveAction = True else: self.moveAction = False if event.type == MOUSEMOTION and self.moveAction: self.sliderpos.x = event.pos[0] self.currentval = int( ((float(self.sliderpos.x) - float(self.position.x)) / float(self.position.width)) * float(self.maxval) ) if self.currentval > self.maxval: self.currentval = self.maxval if self.currentval < self.minval: self.currentval = self.minval if event.type == MOUSEBUTTONUP: self.moveAction = False def draw(self, deltaT): drawsurface = pygame.Surface((self.position.width, self.position.height)) # draw retainer drawsurface.blit(self.rSurface, (0, self.position.height / 2)) # draw slider sliderx = ( ((self.currentval - self.minval) * self.position.width) / (self.maxval - self.minval) ) - self.sSurface.get_width() / 2 self.sliderpos.x = sliderx + self.position.x drawsurface.blit(self.sSurface, (sliderx, 0)) return drawsurface def size(self): return self.position def getCurrentVal(self): return self.currentval
def iterPointsVisibleFromCam(self, cam): #FIXME ptr = self.trackStart #should actually use cam pos as ref while ptr: left = (ptr.left[0]+cam.anchorPt.x,ptr.left[1]+cam.anchorPt.y) right = (ptr.right[0]+cam.anchorPt.x,ptr.right[1]+cam.anchorPt.y) dispRect = Rect(0,0,cam.displayRect.width,cam.displayRect.height) if dispRect.collidepoint(*left) or dispRect.collidepoint(*right): yield [left, right] ptr = ptr.next
def calculateIntersectPoint(p1, p2, p3, p4): p = getIntersectPoint(p1, p2, p3, p4) if p is not None: width = p2[0] - p1[0] height = p2[1] - p1[1] r1 = Rect(p1, (width, height)) r1.normalize() width = p4[0] - p3[0] height = p4[1] - p3[1] r2 = Rect(p3, (width, height)) r2.normalize() # Ensure both rects have a width and height of at least 'tolerance' else the # collidepoint check of the Rect class will fail as it doesn't include the bottom # and right hand side 'pixels' of the rectangle tolerance = 1 if r1.width < tolerance: r1.width = tolerance if r1.height < tolerance: r1.height = tolerance if r2.width < tolerance: r2.width = tolerance if r2.height < tolerance: r2.height = tolerance for point in p: try: res1 = r1.collidepoint(point) res2 = r2.collidepoint(point) if res1 and res2: point = [int(pp) for pp in point] return point except: # sometimes the value in a point are too large for PyGame's Rect class str = "point was invalid ", point print(str) # This is the case where the infinately long lines crossed but # the line segments didn't return None else: return None
def get_monsters_in_range(self, x1, y1, rnge): area = Rect(x1 - rnge, y1 - rnge, 2 * rnge, 2 * rnge) for monster in self.arena.creeps: x2, y2 = monster.rect.center if area.collidepoint((x2, y2)): if sqrt((x1-x2) ** 2 + (y1-y2) ** 2) < rnge: yield monster
class Button(object): def __init__(self, prefs, hotkeys, text, click, centered=None): self.font = prefs.font self.hotkeycolor = prefs.hotkeycolor for c in text.lower(): if c in letters and c not in hotkeys: self.hotkey = c hotkeys.append(self.hotkey) break else: for i in range(1, 11): c = unicode(i % 10) if c not in hotkeys: self.hotkey = c hotkeys.append(self.hotkey) break else: self.hotkey = None self.text = text if self.hotkey: self.text = u': {text}'.format(text=self.text) self.click = click self.location = None self.center = False if centered is None else centered def draw(self, screen): if self.location: s = self.font.render(self.text, True, (255,255,255)) if self.hotkey: h = self.font.render(self.hotkey, True, self.hotkeycolor) t = Surface((h.get_width() + s.get_width(), max(h.get_height(), s.get_height())), flags = s.get_flags()) t.blit(h, (0, 0)) t.blit(s, (h.get_width(), 0)) s = t size = s.get_size() self.rect = Rect([self.location[i]-size[i]/2 for i in range(2)] if self.center else self.location, size) screen.blit(s, self.rect.topleft) @property def size(self): return self.rect.size def handle(self, e): if ((e.type == MOUSEBUTTONDOWN and e.button == 1 and self.rect.collidepoint(e.pos)) or (self.hotkey and e.type == KEYDOWN and e.unicode == self.hotkey)): self.click() return True