Exemplo n.º 1
1
    def test_contains(self):
        r = Rect(1, 2, 3, 4)

        self.failUnless(r.contains(Rect(2, 3, 1, 1)), "r does not contain Rect(2,3,1,1)")
        self.failUnless(r.contains(Rect(r)), "r does not contain the same rect as itself")
        self.failUnless(r.contains(Rect(2, 3, 0, 0)), "r does not contain an empty rect within its bounds")
        self.failIf(r.contains(Rect(0, 0, 1, 2)), "r contains Rect(0,0,1,2)")
        self.failIf(r.contains(Rect(4, 6, 1, 1)), "r contains Rect(4,6,1,1)")
        self.failIf(r.contains(Rect(4, 6, 0, 0)), "r contains Rect(4,6,0,0)")
Exemplo n.º 2
0
    def test_contains(self):
        r = Rect(1, 2, 3, 4)

        self.failUnless(r.contains(Rect(2, 3, 1, 1)),
                        "r does not contain Rect(2,3,1,1)")
        self.failUnless(r.contains(Rect(r)),
                        "r does not contain the same rect as itself")
        self.failUnless(r.contains(Rect(2, 3, 0, 0)),
                        "r does not contain an empty rect within its bounds")
        self.failIf(r.contains(Rect(0, 0, 1, 2)), "r contains Rect(0,0,1,2)")
        self.failIf(r.contains(Rect(4, 6, 1, 1)), "r contains Rect(4,6,1,1)")
        self.failIf(r.contains(Rect(4, 6, 0, 0)), "r contains Rect(4,6,0,0)")
Exemplo n.º 3
0
def _get_group_bounding(tag_store, sizeRect):
    if not isinstance(sizeRect, pygame.Rect):
        sizeRect = Rect(0, 0, sizeRect[0], sizeRect[1])
    if tag_store:
        rects = [tag.rect for tag in tag_store]
        union = rects[0].unionall(rects[1:])
        if sizeRect.contains(union):
            return union
    return sizeRect
Exemplo n.º 4
0
def _get_group_bounding(tag_store, sizeRect):
    if not isinstance(sizeRect, pygame.Rect):
        sizeRect = Rect(0, 0, sizeRect[0], sizeRect[1])
    if tag_store:
        rects = [tag.rect for tag in tag_store]
        union = rects[0].unionall(rects[1:])
        if sizeRect.contains(union):
            return union
    return sizeRect
Exemplo n.º 5
0
def test_within_bounds(pack):
    """Rects packed by the packers lie within the texture bounds."""
    by_bin = packs[pack]

    bounds = Rect(0, 0, 512, 512)
    for bin_id, rects in by_bin.items():
        for r in rects:
            if not bounds.contains(r):
                raise AssertionError(f"{r} is not within bounds {bounds}")
Exemplo n.º 6
0
    def test_fit(self):
        # __doc__ (as of 2008-08-02) for pygame.rect.Rect.fit:

        # Rect.fit(Rect): return Rect
        # resize and move a rectangle with aspect ratio
        #
        # Returns a new rectangle that is moved and resized to fit another.
        # The aspect ratio of the original Rect is preserved, so the new
        # rectangle may be smaller than the target in either width or height.

        r = Rect(10, 10, 30, 30)

        r2 = Rect(30, 30, 15, 10)

        f = r.fit(r2)
        self.assertTrue(r2.contains(f))

        f2 = r2.fit(r)
        self.assertTrue(r.contains(f2))
Exemplo n.º 7
0
    def test_fit(self):

        # __doc__ (as of 2008-08-02) for pygame.rect.Rect.fit:

          # Rect.fit(Rect): return Rect
          # resize and move a rectangle with aspect ratio
          # 
          # Returns a new rectangle that is moved and resized to fit another.
          # The aspect ratio of the original Rect is preserved, so the new
          # rectangle may be smaller than the target in either width or height.

        r = Rect(10, 10, 30, 30)

        r2 = Rect(30, 30, 15, 10)

        f = r.fit(r2)
        self.assertTrue(r2.contains(f))
        
        f2 = r2.fit(r)
        self.assertTrue(r.contains(f2))
Exemplo n.º 8
0
    def query(self, rect: Rect):
        if not self.rect.colliderect(rect):
            return

        if self.items:
            yield from (i for i in self.items if rect.contains(i.rect))
        elif hasattr(self, 'ne'):
            yield from self.ne.query(rect)
            yield from self.nw.query(rect)
            yield from self.se.query(rect)
            yield from self.sw.query(rect)
Exemplo n.º 9
0
class Unit(object):
    def __init__(self, player, coord, ai, hp, speed):
        """
        Arguments:
        - `player`: The player that this unit fights for.
        - `coord`: The coordinates of the unit.
        - `ai`: An AI object to control the unit.
        """
        self.player = player
        self.rect = Rect(coord[0] - 5, coord[1] - 5, 10, 10)
        self.coord = coord
        self.ai = ai
        self.hp = hp
        self.speed = speed

    def move(self, world, dest):
        "Move along the shortest path to the destination"
        if dist(self.rect.center, dest) <= self.speed:
            self.coord = dest
            self.rect.center = dest
        else:
            if dest == self.rect.center:
                return
            a = dest[0] - self.coord[0]
            b = dest[1] - self.coord[1]
            d = math.sqrt(a ** 2 + b ** 2) / self.speed
            self.coord = (self.coord[0] + a / d, self.coord[1] + b / d)
            self.rect.center = self.coord

    def act(self, world):
        raise NotImplemented("%s has not implemented act()" % type(self))

    def blit(self, screen):
        raise NotImplemented("%s has not implemented blit()" % type(self))

    def contains(self, p):
        if type(p) == pygame.Rect:
            return self.rect.contains(p)
        else:
            return self.rect.contains(pygame.Rect(p[0], p[1], 1, 1))
Exemplo n.º 10
0
class Canvas(object):
    def __init__(self, size, slot_size):
        self.area_rect = Rect((0,0), size)
        self.slot_size = slot_size
        self._rects_of_slot = {}
        self._slots_of_entry = {}

    def _slot_keys_of_rect(self, rect):
        slot_width, slot_height = self.slot_size
        for x in xrange(rect.left//slot_width, 1+rect.right//slot_width):
            for y in xrange(rect.top//slot_height, 1+rect.bottom//slot_height):
                yield x, y
        
    def _add(self, rect, entry):
        if entry in self._slots_of_entry:
            raise EntryAlreadyExists("Entry already in Canvas")
        assert entry not in self._slots_of_entry
        
        assert self.area_rect.contains(rect)

        self._slots_of_entry[entry] = slots = []
        for slot_key in self._slot_keys_of_rect(rect):
            self._rects_of_slot.setdefault(slot_key, {})[entry] = rect
            slots.append(slot_key)

    def add(self, entry):
        self._add(entry.bounding_rect(), entry)

    def remove(self, entry):
        for slot_key in self._slots_of_entry[entry]:
            del self._rects_of_slot[slot_key][entry]
        del self._slots_of_entry[entry]

    def clear(self):
        self._rects_of_slot.clear()
        self._slots_of_entry.clear()

    def _rect_collisions(self, rect):
        for slot_key in self._slot_keys_of_rect(rect):
            for entry, cur_rect in self._rects_of_slot.get(slot_key, {}).iteritems():
                if rect.colliderect(cur_rect):
                    yield entry
    
    def collisions(self, entry):
        for other_entry in self._rect_collisions(entry.bounding_rect()):
            if entry.collides_with(other_entry):
                yield other_entry

    def items(self):
        return self._slots_of_entry.iterkeys()
Exemplo n.º 11
0
class Unit(object):
    def __init__(self, player, coord, ai, hp, speed):
        """
        Arguments:
        - `player`: The player that this unit fights for.
        - `coord`: The coordinates of the unit.
        - `ai`: An AI object to control the unit.
        """
        self.player = player
        self.rect = Rect(coord[0] - 5, coord[1] - 5, 10, 10)
        self.coord = coord
        self.ai = ai
        self.hp = hp
        self.speed = speed

    def move(self, world, dest):
        "Move along the shortest path to the destination"
        if dist(self.rect.center, dest) <= self.speed:
            self.coord = dest
            self.rect.center = dest
        else:
            if dest == self.rect.center: return
            a = dest[0] - self.coord[0]
            b = dest[1] - self.coord[1]
            d = math.sqrt(a**2 + b**2) / self.speed
            self.coord = (self.coord[0] + a / d, self.coord[1] + b / d)
            self.rect.center = self.coord

    def act(self, world):
        raise NotImplemented("%s has not implemented act()" % type(self))

    def blit(self, screen):
        raise NotImplemented("%s has not implemented blit()" % type(self))

    def contains(self, p):
        if type(p) == pygame.Rect: return self.rect.contains(p)
        else: return self.rect.contains(pygame.Rect(p[0], p[1], 1, 1))
Exemplo n.º 12
0
    def for_rect(cls, tex, rect: Rect):
        """Create a TextureRegion for the given texture and rect."""
        if isinstance(tex, TextureRegion):
            assert rect.width and rect.height, "Invalid rect dimensions"
            myrect = Rect(0, 0, tex.width, tex.height)
            assert myrect.contains(rect), "Subrect is not in bounds."

            coords = tex.texcoords.astype(np.int32)
            lb = coords[3]
            r = np.sign(coords[2] - lb)
            u = np.sign(coords[0] - lb)
            lb += r * rect.left + u * rect.top
            across = r * rect.width
            up = u * rect.height
            texcoords = np.array([
                lb + up,
                lb + up + across,
                lb + across,
                lb,
            ], dtype=np.uint16)
            rot = tex.rot
            tex = tex.tex
        else:
            rot = 0

            l = rect.left
            b = rect.top
            r = rect.right
            t = rect.bottom
            texcoords = np.array([
                (l, t),
                (r, t),
                (r, b),
                (l, b),
            ], dtype=np.uint16)
        return cls(
            tex,
            rect.width,
            rect.height,
            texcoords,
            rot
        )
Exemplo n.º 13
0
 def paint(self, hierarchy: Graph, shapes: List[Shape],
           viewing_window: Rect, action_dict):
     """
     Paints an image based on a relationship graph provided
     :param action_dict: dict of kind -> texture function each texture function gets (hierarchy, shapes and shape)
     :param hierarchy: interpreted shape hierarchy
     :param shapes: list of shapes read by the Loader
     :param viewing_window: viewing window of the hierarchy shapes
     :return: png
     """
     img = np.zeros(
         (int(viewing_window.width), int(viewing_window.height), 3))
     # Fun mode
     # img = np.empty((viewing_window.height, viewing_window.width, 3))
     drawn_shapes = [
         shape for shape in shapes if viewing_window.contains(shape.shape)
         or viewing_window.colliderect(shape.shape)
     ]
     hs = list(zip(hierarchy.nodes, drawn_shapes))
     for i in range(len(hs)):
         node = hs[i][0]
         shape = hs[i][1]
         logging.info(
             f"Generating texture for shape {shape.id} with kind {shape.kind}"
         )
         texture = action_dict[shape.kind].paint(hierarchy, shapes, shape)
         # Get indices
         logging.info(
             f"Getting indices for shape {shape} and viewing window {viewing_window}"
         )
         x1, x2, y1, y2 = get_splices(viewing_window, shape.shape)
         # Reshape the texture to fit (hopefully)
         logging.info(f"Indices are {x1}, {x2}, {y1}, {y2}")
         resize = np.resize(texture, (x2 - x1, y2 - y1, 3))
         img[x1:x2, y1:y2] = resize
     # for i in range(len(hs)):
     #     shape = hs[i][1]
     #     node = hs[i][0]
     #     anchor = camera.world_to_cam([shape.left, shape.up])
     #     draw.text((anchor[0], anchor[1]), f"{hash(shape)}", fill=(255, 255, 255))
     return cv2.flip(cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE), 1)
Exemplo n.º 14
0
    def collision_check(self):
        ''' Method for checking if the entity has run into a tree or something
            and move it back a pixel if it has
        '''
        if self.wall_collides:
            # Move the entity inside of the window (border collision)
            entity_rect = Rect(self.x, self.y, self.width,self.height)
            window_rect = Rect(0, 0, g.width * c.TILE_SIZE, g.height * c.TILE_SIZE)
            if not window_rect.contains(entity_rect):
                entity_rect.clamp_ip(window_rect)
                self.x = entity_rect.left
                self.y = entity_rect.top

        if self.collides:
            # Make sure collision rectangles are up to date
            self.update_collision_rects()
            # Get the tile the entity is standing on
            tile_pos = self.get_tile()
            checked_tiles = []
            # Loop through a 3x3 tile square around the entity, to not check the entire map
            for i in range(tile_pos[0] - 1, tile_pos[0] + 2):
                for j in range(tile_pos[1] - 1, tile_pos[1] + 2):
                    try:
                        if c.IMAGES[g.map[i][j].type].collides:
                            checked_tiles.append(g.map[i][j].rect())
                    except IndexError:
                        # That index was apparently outside of the map
                        pass
                    except:
                        raise
                    
            # Check if each of the zones collides with any of the tiles
            if self.col_left.collidelist(checked_tiles) != -1:
                self.x += 1
            if self.col_right.collidelist(checked_tiles) != -1:
                self.x -= 1
            if self.col_bottom.collidelist(checked_tiles) != -1:
                self.y -= 1
            if self.col_top.collidelist(checked_tiles) != -1:
                self.y += 1
Exemplo n.º 15
0
    def collision_check(self):
        """ Method for checking if the entity has run into a tree or something
            and move it back a pixel if it has
        """
        if self.wall_collides:
            # Move the entity inside of the window (border collision)
            entity_rect = Rect(self.x, self.y, self.width,self.height)
            window_rect = Rect(0, 0, g.width * c.TILE_SIZE, g.height * c.TILE_SIZE)
            if not window_rect.contains(entity_rect):
                entity_rect.clamp_ip(window_rect)
                self.x = entity_rect.left
                self.y = entity_rect.top

        collided = False
        if self.collides:
            # Make sure collision rectangles are up to date
            self.update_collision_rects()
            # Get the tile the entity is standing on
            tile_pos = self.get_tile()
            checked_tiles = []
            # Loop through a 3x3 tile square around the entity, to not check the entire map
            for i in range(tile_pos[0] - 1, tile_pos[0] + 2):
                for j in range(tile_pos[1] - 1, tile_pos[1] + 2):
                    try:
                        if c.IMAGES[g.map[i][j].type].collides:
                            checked_tiles.append(g.map[i][j].rect())
                    except IndexError:
                        # That index was apparently outside of the map
                        pass

            # Check if each of the zones collides with any of the tiles
            # If so, move it in the appropriate direction, specified in update_collision_rects() as the keys
            for rect in self.rects:
                if self.rects[rect].collidelist(checked_tiles) != -1:
                    self.x += rect[0]
                    self.y += rect[1]
                    collided = True

        self.collided = collided
Exemplo n.º 16
0
class GameButton:
    rect = None
    unselected_img = None
    selected_img = None

    def __init__(self, image, y, width, height):
        self.rect = Rect((603 - width) / 2, y, width, height / 2)
        self.unselected_img = image.subsurface((0, 0, width, height))
        self.selected_img = image.subsurface((0, height, width, height))
        self.unselected_img = transform.scale(self.unselected_img,
                                              (width, int(height / 2)))
        self.selected_img = transform.scale(self.selected_img,
                                            (width, int(height / 2)))
        self.is_selected = False

    def contains_mouse(self, mouse_pos):
        return self.rect.contains((mouse_pos.x, mouse_pos.y, 0, 0))

    def render(self, mouse_pos):
        Constant.screen.blit(
            self.selected_img if self.contains_mouse(mouse_pos) else
            self.unselected_img, self.rect)
Exemplo n.º 17
0
    def test_contains(self):
        r = Rect(1, 2, 3, 4)

        self.assertTrue(r.contains(Rect(2, 3, 1, 1)),
                        "r does not contain Rect(2, 3, 1, 1)")
        self.assertTrue(r.contains(Rect(r)),
                        "r does not contain the same rect as itself")
        self.assertTrue(
            r.contains(Rect(2, 3, 0, 0)),
            "r does not contain an empty rect within its bounds",
        )
        self.assertFalse(r.contains(Rect(0, 0, 1, 2)),
                         "r contains Rect(0, 0, 1, 2)")
        self.assertFalse(r.contains(Rect(4, 6, 1, 1)),
                         "r contains Rect(4, 6, 1, 1)")
        self.assertFalse(r.contains(Rect(4, 6, 0, 0)),
                         "r contains Rect(4, 6, 0, 0)")
Exemplo n.º 18
0
Arquivo: map.py Projeto: bpa/renegade
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 )
Exemplo n.º 19
0
class OrbitPanel(BaseWidget):
    current = None  # ahora será la estrella o sistema seleccionado.
    curr_idx = None  # ahora será el layer de self.Buttons.
    selected_marker = None

    last_idx = 0
    _loaded_orbits = None

    offset = 0
    curr_x, curr_y = 3, 442
    curr_digit = 0

    visible_markers = True
    orbits = None
    markers = None
    buttons = None

    skippable = False

    no_star_error = False

    def __init__(self, parent):
        super().__init__(parent)
        self.name = 'Orbit'
        self.image = Surface((ANCHO, ALTO - 32))
        self.image.fill(COLOR_BOX)
        self.rect = self.image.get_rect()
        self.properties = WidgetGroup()
        self.area_buttons = self.image.fill(COLOR_AREA,
                                            [0, 420, self.rect.w, 200])
        self.area_markers = Rect(3, 58, 380, 20 * 16)
        self.area_scroll = Rect(3, 32, 387, 388)
        self.area_modify = ModifyArea(self, ANCHO - 201, 374)

        self.f = self.crear_fuente(16, underline=True)
        self.order_f = self.crear_fuente(14)
        self.write(self.name + ' Panel',
                   self.f,
                   centerx=(ANCHO // 4) * 1.5,
                   y=0)
        self.planet_area = AvailablePlanets(self, ANCHO - 200, 32, 200, 340)
        self.recomendation = Recomendation(self, 80, ALTO // 2 - 130)

        self._loaded_orbits = []
        self.indexes = []

        self._orbits = {}
        self._buttons = {}
        self._markers = {}

        self.orbit_descriptions = WidgetGroup()
        self.show_markers_button = ToggleableButton(self, 'Stellar Orbits',
                                                    self.toggle_stellar_orbits,
                                                    3, 421)
        self.show_markers_button.disable()
        self.add_orbits_button = AddOrbitButton(self, ANCHO - 94, 394)
        self.resonances_button = AddResonanceButton(self, ANCHO - 140, 416)

        self.digit_x = RatioDigit(self, 'x',
                                  self.resonances_button.rect.left - 60,
                                  self.resonances_button.rect.y)
        self.write(':',
                   self.crear_fuente(16),
                   topleft=[
                       self.digit_x.rect.right + 1,
                       self.resonances_button.rect.y - 1
                   ])
        self.digit_y = RatioDigit(self, 'y', self.digit_x.rect.right + 9,
                                  self.resonances_button.rect.y)
        self.ratios = [self.digit_x, self.digit_y]
        self.cycler = cycle(self.ratios)
        next(self.cycler)

        self.properties.add([
            self.area_modify, self.planet_area, self.show_markers_button,
            self.add_orbits_button, self.resonances_button, self.digit_x,
            self.digit_y
        ],
                            layer=2)
        EventHandler.register(self.clear, 'ClearData')
        EventHandler.register(self.save_orbits, 'Save')
        EventHandler.register(self.load_orbits, 'LoadData')

    def set_current(self):
        self.toggle_current_markers_and_buttons(False)
        star = Systems.get_current_star()
        self.current = star
        self.curr_idx = self.indexes.index(star)
        self.orbits = self._orbits[star]
        self.markers = self._markers[star]
        self.buttons = self._buttons[star]
        if not len(self.markers) or not self.markers[0].locked:
            self.populate()
        self.toggle_current_markers_and_buttons(True)
        self.sort_buttons()
        self.add_orbits_button.enable()
        self.visible_markers = False
        self.toggle_stellar_orbits()

    def populate(self):
        star = self.current
        markers = {
            'Inner Boundary': star.inner_boundry,
            'Habitable Inner': star.habitable_inner,
            'Habitable Outer': star.habitable_outer,
            'Frost Line': star.frost_line,
            'Outer Boundary': star.outer_boundry
        }

        for marker in markers:
            x = OrbitMarker(self, marker, star, markers[marker])
            x.locked = True
            self._markers[star].append(x)
            self.properties.add(x, layer=4)

        if hasattr(star, 'habitable_orbit'):
            markers = {
                'Inner Forbbiden Zone': star.inner_forbbiden_zone,
                'Outer Forbbiden Zone': star.outer_forbbiden_zone
            }
            for marker in markers:
                x = OrbitMarker(self, marker, star, markers[marker])
                x.locked = True
                self._markers[star].append(x)
                self.properties.add(x, layer=4)
            self.add_orbit_marker(star.habitable_orbit)

        self.sort_markers()

    def toggle_current_markers_and_buttons(self, toggle: bool):
        if self.markers is not None:
            for marker in self.markers:
                marker.toggle(toggle)
        if self.buttons is not None:
            for button in self.buttons:
                button.toggle(toggle)

    def add_orbit_marker(self, position, resonance=False):
        star = self.current if not hasattr(position, 'star') else position.star
        inner = star.inner_boundry
        outer = star.outer_boundry
        bc = False if resonance is False else True
        if type(position) is q:
            ba = True
            bb = False
            if not resonance:
                test = inner < position < outer
                color = COLOR_TEXTO
            else:
                test = inner < position  # TNOs orbit well outside of 40AUs.
                color = (255, 0, 0)  # color provisorio
        else:  # type(position) is PlanetOrbit
            ba = False
            bb = True
            test = True  # saved orbits are valid by definition
            color = COLOR_STARORBIT

        if test is True:
            new = OrbitMarker(self,
                              'Orbit',
                              star,
                              position,
                              is_orbit=ba,
                              is_complete_orbit=bb,
                              is_resonance=bc)
            self._markers[star].append(new)
            self._orbits[star].append(new)
            self.sort_markers()
            self.add_button_and_type(star, new, color)
            self.properties.add(new, layer=4)

    def add_button_and_type(self, star, marker, color):
        orbit_type = OrbitType(self)
        button = OrbitButton(self, color)
        self._buttons[star].append(button)

        # Buttons, OrbitTypes and Markers are all Intertwined.
        orbit_type.intertwine(m=marker, b=button)
        button.intertwine(m=marker, o=orbit_type)
        marker.intertwine(o=orbit_type, b=button)

        self.orbit_descriptions.add(orbit_type)
        if len(self.buttons):
            self.sort_buttons()
        self.properties.add(button, layer=4)
        self.properties.add(orbit_type, layer=4)
        button.enable()

    def sort_markers(self):
        self.markers.sort(key=lambda m: m.value)
        for i, marker in enumerate(self.markers, start=1):
            marker.rect.y = i * 2 * 10 + 38 + self.offset
            if not self.area_markers.contains(marker.rect):
                marker.hide()
            else:
                marker.show()

    def sort_buttons(self):
        x, y = self.curr_x, self.curr_y
        for bt in sorted(self.buttons, key=lambda b: b.get_value().m):
            bt.move(x, y)
            if not self.area_buttons.contains(bt.rect):
                bt.hide()
            else:
                bt.show()
            if x + bt.rect.w + 15 < self.rect.w - bt.rect.w + 15:
                x += bt.rect.w + 15
            else:
                x = 3
                y += 32

    def delete_marker(self, marker):
        """
        :type marker: OrbitMarker
        """
        if not marker.locked:
            marker.kill()
            marker.linked_type.kill()
            marker.linked_button.kill()
            if marker is self.area_modify.marker:
                self.area_modify.unlink()
            idx = self.markers.index(marker)
            del self.markers[idx]
            self.buttons.remove(marker.linked_button)
            self.sort_markers()
            self.sort_buttons()

    def on_mousebuttondown(self, event):

        if self.area_scroll.collidepoint(event.pos):
            last_is_hidden = not self.markers[-1].is_visible
            if len(self.markers) > 16 and event.button in (4, 5):
                if event.button == 4 and self.offset < 0:
                    self.offset += 20
                elif event.button == 5 and last_is_hidden:
                    self.offset -= 20

                self.sort_markers()

        elif self.area_buttons.collidepoint(
                event.pos) and self.buttons is not None and len(self.buttons):
            self.buttons.sort(key=lambda b: b.get_value().m)
            last_is_hidden = not self.buttons[-1].is_visible
            first_is_hidden = not self.buttons[0].is_visible
            if event.button == 4 and first_is_hidden:
                self.curr_y += 32
            elif event.button == 5 and last_is_hidden:
                self.curr_y -= 32
            self.sort_buttons()

        elif event.button == 1 and self.markers is not None:
            for marker in self.markers:
                marker.deselect()
                marker.enable()

    def check_orbits(self):
        self.orbits.sort(key=lambda o: o.value.m)
        for x, p in enumerate(self.orbits[1:], start=1):
            a = self.orbits[x - 1].value.m if x > 0 and len(
                self.orbits) else self.orbits[0].value.m  # el anterior
            assert a + 0.15 < p.value.m, 'Orbit @' + str(
                p.value.m) + ' is too close to Orbit @' + str(a)

            if x + 1 < len(self.orbits):
                b = self.orbits[x + 1].value.m  # el posterior
                assert p.value.m < b - 0.15, 'Orbit @' + str(
                    p.value.m) + ' is too close to Orbit @' + str(b)

    def anchor_maker(self, marker):
        self.area_modify.link(marker)
        self.selected_marker = marker

    def clear(self, event):
        if event.data['panel'] is self:
            for marker in self.markers:
                marker.kill()
            for orbit in self.buttons:
                orbit.kill()
            self.markers.clear()
            self.clear_ratios()

    def save_orbits(self, event):
        orbits = self._loaded_orbits
        for system in Systems.get_systems():
            if system.star_system.letter == 'S':
                for star in system:
                    for marker in self._orbits.get(star, []):
                        d = self.create_save_data(marker.orbit)
                        orbits.append(d)
            else:
                star = system.star_system
                for marker in self._orbits.get(star, []):
                    d = self.create_save_data(marker.orbit)
                    orbits.append(d)

        EventHandler.trigger(event.tipo + 'Data', 'Orbit',
                             {'Stellar Orbits': orbits})

    @staticmethod
    def create_save_data(orb):
        d = {}
        if hasattr(orb, 'semi_major_axis'):
            d['a'] = round(orb.semi_major_axis.m, 2)
        if hasattr(orb, 'inclination'):
            d['i'] = orb.inclination.m
        if hasattr(orb, 'eccentricity'):
            d['e'] = orb.eccentricity.m
        if hasattr(orb, 'astrobody'):
            d['astrobody'] = orb.astrobody.id
            d['star_id'] = orb.astrobody.orbit.star.id
        return d

    def load_orbits(self, event):
        for position in event.data.get('Stellar Orbits', []):
            if position not in self._loaded_orbits:
                self._loaded_orbits.append(position)

    def set_loaded_orbits(self):
        for orbit_data in self._loaded_orbits:
            a = q(orbit_data['a'], 'au')
            if 'e' not in orbit_data:
                self.add_orbit_marker(a)
            else:
                e = q(orbit_data['e'])
                i = q(orbit_data['i'], 'degree')
                system = Systems.get_system_by_id(orbit_data['star_id'])
                planet = system.get_astrobody_by(orbit_data['astrobody'],
                                                 tag_type='id')
                star = system.star_system
                planet.set_orbit(star, [a, e, i])
                self.add_orbit_marker(planet.orbit)
                self.planet_area.delete_objects(planet)

        # borrar las órbitas cargadas para evitar que se dupliquen.
        self.sort_markers()
        self._loaded_orbits.clear()

    def fill_indexes(self):
        assert len(Systems.get_systems())
        for system in Systems.get_systems():
            star = system.star_system
            if star not in self._markers:
                self._markers[star] = []
                self._orbits[star] = []
                self._buttons[star] = []
                self.indexes.append(star)

    def show(self):
        try:
            self.fill_indexes()
            self.set_current()
            self.no_star_error = False

        except AssertionError:
            self.no_star_error = True

        for prop in self.properties.get_widgets_from_layer(2):
            prop.show()
        self.visible_markers = True
        if len(self._loaded_orbits):
            self.set_loaded_orbits()
        self.show_markers_button.show()

        super().show()

    def hide(self):
        super().hide()
        for item in self.properties.widgets():
            item.hide()

    def toggle_stellar_orbits(self):
        if self.visible_markers:
            self.area_modify.color_alert()
            self.add_orbits_button.disable()
            for marker in self.markers:
                marker.hide()
        else:
            for marker in self.markers:
                marker.show()
            self.hide_orbit_types()
            self.show_markers_button.disable()
            self.add_orbits_button.enable()
            self.area_modify.color_standby()
        self.visible_markers = not self.visible_markers
        self.area_modify.visible_markers = self.visible_markers

    def hide_orbit_types(self):
        for orbit_type in self.orbit_descriptions.widgets():
            orbit_type.hide()
        for orbit_button in self.buttons:
            orbit_button.unlock()

    def deselect_markers(self, m):
        for marker in self.markers:
            marker.deselect()
            marker.enable()
        m.select()

    def link_astrobody_to_stellar_orbit(self, astrobody):
        locked = [i for i in self.buttons if i.locked]
        if len(locked):
            orbit = PseudoOrbit(locked[0].linked_marker.orbit)
            locked[0].linked_marker.orbit = orbit
            locked[0].linked_type.show()
            locked[0].linked_type.link_astrobody(astrobody)
            self.add_orbits_button.disable()
            if astrobody.celestial_type == 'planet':
                self.recomendation.suggest(astrobody, orbit,
                                           Systems.get_current_star())
                self.recomendation.show_suggestion(astrobody,
                                                   orbit.temperature)

    def update(self):
        super().update()
        idx = Systems.get_current_idx()
        if idx != self.last_idx:
            self.set_current()
            self.last_idx = idx

        if not self.no_star_error:
            self.image.fill(COLOR_BOX, self.area_markers)
        else:
            f = self.crear_fuente(16)
            text = 'There is no star system set. Go back to the Star Panel and set a star first.'
            rect = Rect(50, 100, 200, 100)
            render = render_textrect(text, f, rect.w, (0, 0, 0), COLOR_BOX)
            self.image.blit(render, rect)

    def __repr__(self):
        return 'Orbit Panel'

    def set_current_digit(self, idx):
        self.curr_digit = self.ratios.index(idx)

    def cycle(self):
        has_values = False
        for ratio in self.ratios:
            ratio.deselect()
            has_values = ratio.value != ''

        valid = has_values and not self.no_star_error
        valid = valid and self.selected_marker is not None

        if valid:
            self.resonances_button.enable()
        else:
            ratio = next(self.cycler)
            ratio.select()
            WidgetHandler.set_origin(ratio)

    def ratios_to_string(self):
        x = int(self.digit_x.value)
        y = int(self.digit_y.value)
        assert x >= y, 'invalid ratio'
        self.write('{}° Order'.format(x - y),
                   self.order_f,
                   right=self.digit_x.rect.left - 2,
                   y=self.digit_x.rect.y)
        return '{}:{}'.format(x, y)

    def clear_ratios(self):
        self.digit_x.clear()
        self.digit_y.clear()
Exemplo n.º 20
0
def reverse_clamp_ip(larger_rect: Rect, smaller_rect: Rect):
    if not larger_rect.contains(smaller_rect):
        larger_rect.left = min(larger_rect.left, smaller_rect.left)
        larger_rect.right = max(larger_rect.right, smaller_rect.right)
        larger_rect.top = min(larger_rect.top, smaller_rect.top)
        larger_rect.bottom = max(larger_rect.bottom, smaller_rect.bottom)
Exemplo n.º 21
0
class Dungeons():
    def __init__(self, space_size=(400, 600), n_rooms=7):

        #list of all rooms
        self.rooms = []

        #walls
        self.walls = []

        #list of all coridors
        self.corridors = []

        #list of all shapes on the map (to create full topolical map later)
        shapes = []

        self.space_size = space_size
        grid_size = WALL_SIZE
        self.space_Rect = Rect(0, 0, space_size[0], space_size[1])

        max_room_size = MAX_ROOM_SIZE / grid_size
        min_room_size = MIN_ROOM_SIZE / grid_size

        space_grid = self.space_size[0] / grid_size, space_size[1] / grid_size
        all_rooms = geo.Polygon()

        for ii in range(n_rooms):
            room_width = grid_size * rand.randint(min_room_size, max_room_size)
            room_height = grid_size * rand.randint(min_room_size,
                                                   max_room_size)
            room_center = grid_size * (rand.randint(
                1, space_grid[0] - 1)), grid_size * (rand.randint(
                    1, space_grid[1] - 1))
            new_room = Room(room_center, room_width, room_height)

            dist = new_room.ring.distance(all_rooms)
            out_of_bounds = not self.space_Rect.contains(new_room)
            while self.rooms and dist < WALL_SIZE or out_of_bounds:
                room_width = grid_size * rand.randint(min_room_size,
                                                      max_room_size)
                room_height = grid_size * rand.randint(min_room_size,
                                                       max_room_size)
                room_center = grid_size * (rand.randint(
                    1, space_grid[0] - 1)), grid_size * (rand.randint(
                        1, space_grid[1] - 1))
                new_room = Room(room_center, room_width, room_height)
                #keys = new_room.collidelistall(self.rooms)
                dist = new_room.ring.distance(all_rooms)
                out_of_bounds = not self.space_Rect.contains(new_room)

            #create corridors
            for room in self.rooms:
                corridor = Corridor(new_room, room)
                self.corridors.append(corridor)
                new_room.corridors.append(self.corridors[-1])
                room.corridors.append(self.corridors[-1])
                shapes.append(corridor.ring)

            self.rooms.append(new_room)
            shapes.append(new_room.ring)
            all_rooms = all_rooms.union(new_room.ring)

        # remove the corridors that intersect with rooms
        # TODO: Attention: the corridors are only being removed from the full list of corridors in self, but not from the lists that are coresponding to each of the rooms
        # TODO: Clean up, it can be easier!
        new_corridors = []
        for corridor in self.corridors:
            own_rooms = corridor.room_h.ring.union(corridor.room_v.ring)
            own_room_walls = corridor.room_h.wall_polygons + corridor.room_v.wall_polygons
            current_all_rooms = all_rooms.difference(own_rooms)
            if current_all_rooms.is_empty or (
                    corridor.ring.distance(current_all_rooms) > 10):
                walls_own_rooms = geo.Polygon()
                for wall in own_room_walls:
                    walls_own_rooms = walls_own_rooms.union(wall)
                if walls_own_rooms.intersection(
                        corridor.ring
                ).area <= 2 * CORRIDOR_SIZE * CORRIDOR_SIZE:
                    new_corridors.append(corridor)

        self.corridors = new_corridors
        self.corridors = [
            x for x in self.corridors
            if not x.ring.intersection(all_rooms).length > Corridor.narrow * 4
        ]

        #create topological map
        self.topology = self.rooms[0].ring
        for room in self.rooms:
            self.topology = self.topology.union(room.ring)

        for jj in range(len(self.corridors)):
            self.corridors[jj].ring = self.corridors[jj].ring.difference(
                self.topology)

        for jj in range(len(self.corridors)):
            self.topology = self.topology.union(self.corridors[jj].ring)

        walls = []
        #create walls
        for jj in range(len(self.rooms)):
            for ii in range(len(self.rooms[jj].wall_polygons)):
                self.rooms[jj].wall_polygons[ii] = self.rooms[
                    jj].wall_polygons[ii].difference(self.topology)
                #wall = Wall(self.rooms[jj].wall_polygons[ii].boundary)
                walls.append(
                    (self.rooms[jj].wall_polygons[ii], self.rooms[jj].texture))

        for jj in range(len(self.corridors)):
            for ii in range(len(self.corridors[jj].wall_polygons)):

                self.corridors[jj].wall_polygons[ii] = self.corridors[
                    jj].wall_polygons[ii].difference(self.topology)
                #print(self.corridors[jj].wall_polygons[ii])
                if not self.corridors[jj].wall_polygons[ii].is_empty:
                    walls.append((self.corridors[jj].wall_polygons[ii],
                                  self.corridors[jj].texture))
                    #draw_multilinestring(self.corridors[jj].wall_polygons[ii].boundary, screen)

        print(len(walls))
        walls__ = convert_to_list_of_poly(walls)
        print(len(walls__))

        for wall in walls__:
            print(wall)
            # print (wall[1])
            # wall_ = Wall(wall[0].boundary, texture=wall[1])
            self.walls.append(wall)
        #TODO: check connectivity: this is implemented on the level of the environment, but should be moved here

    def generate_random_point(self, n_points=1, pymunk_coordinates=True):
        #fundtion to generate random point inside of the map (eg for the fruits)
        ll = []
        bb = self.topology.bounds
        for ii in range(n_points):
            p = (rand.randint(bb[0], bb[2]), rand.randint(bb[1], bb[3]))
            while not self.topology.contains(geo.Point(p)):
                p = (rand.randint(bb[0], bb[2]), rand.randint(bb[1], bb[3]))

            if pymunk_coordinates:
                ll.append((p[0], self.space_size[1] - p[1]))
            else:
                ll.append((p[0], p[1]))
        return ll

    def draw(self):
        #standalone display of the topological elements of the map using pygame engine
        #this is mainly needed for debugging, hence not removing old code
        pygame.init()
        screen = pygame.display.set_mode(self.space_size)

        #for room in self.rooms:
        #pygame.draw.rect(screen, (0, 255, 255), room, 2)

        # for corridor in self.corridors:
        #     pygame.draw.rect(screen, (0, 255, 255), corridor.h, 2)
        #     pygame.draw.rect(screen, (0, 255, 255), corridor.v, 2)

        # for corridor in self.corridors:
        #     print(corridor.ring.boundary)
        #     array_of_points = np.array(corridor.ring.boundary)
        #     for ii in range(1, array_of_points.shape[0]):
        #        pygame.draw.line(screen, (255, 255, 0), array_of_points[ii-1, :], array_of_points[ii, :], 2)
        #        print(array_of_points[ii-1, :], array_of_points[ii, :])
        #     pygame.draw.line(screen, (255, 255, 0), array_of_points[-1, :], array_of_points[0, :], 2)
        #     # # for ii in range(1, array_of_points.shape[0]):
        #     #     pygame.draw.line(screen, (255, 255, 0), array_of_points[ii-1, :], array_of_points[ii, :], 2)
        #     #     print(array_of_points[ii-1, :], array_of_points[ii, :])
        #     # pygame.draw.line(screen, (255, 255, 0), array_of_points[-1, :], array_of_points[0, :], 2)
        #
        #     # for x in np.nditer(array_of_points):
        #     #     pygame.draw.line(screen, (0, 255, 0), line_[x, :], line_[1, :], 2)
        #     # #pygame.draw.rect(screen, (255, 0, 0), corridor.v, 2)
        #     #pygame.draw.rect(screen, (255, 0, 0), corridor.h, 2)

        draw_multilinestring(self.topology.boundary, screen)

        #for room in self.rooms:
        #draw_linearring(room.outer_line.boundary, screen)

        # for jj in range(len(self.rooms)):
        #     for ii in range(len(self.rooms[jj].wall_polygons)):
        #         self.rooms[jj].wall_polygons[ii] = self.rooms[jj].wall_polygons[ii].difference(self.topology)
        #         draw_multilinestring(self.rooms[jj].wall_polygons[ii].boundary, screen)
        #
        #
        # for jj in range(len(self.corridors)):
        #     for ii in range(len(self.corridors[jj].wall_polygons)):
        #
        #             self.corridors[jj].wall_polygons[ii] = self.corridors[jj].wall_polygons[ii].difference(self.topology)
        #             print(self.corridors[jj].wall_polygons[ii])
        #             if not self.corridors[jj].wall_polygons[ii].is_empty:
        #                 draw_multilinestring(self.corridors[jj].wall_polygons[ii].boundary, screen)
        #

        for wall in self.walls:
            pygame.draw.rect(
                screen, (0, 255, 255),
                Rect(wall.x - 0.5 * wall.width, wall.y - 0.5 * wall.height,
                     wall.width, wall.height), 2)
            pygame.draw.circle(
                screen, (255, 0, 0),
                self.generate_random_point(pymunk_coordinates=False)[-1], 5, 1)
        # print(self.topology.boundary)
        # sh = geo.shape(self.topology.boundary)
        # for line in sh:
        #     array_of_points = np.array(line)
        #     for ii in range(1, array_of_points.shape[0]):
        #         pygame.draw.line(screen, (255, 255, 0), array_of_points[ii - 1, :], array_of_points[ii, :], 2)
        #         print(array_of_points[ii - 1, :], array_of_points[ii, :])
        #     pygame.draw.line(screen, (255, 255, 0), array_of_points[-1, :], array_of_points[0, :], 2)

        # for line in sh:
        #     print (np.array(line))
        #     line_ = np.array(line)
        #     pygame.draw.line(screen, (0, 255, 0), line_[0, :], line_[1, :], 2)

        pygame.display.update()

        clock = pygame.time.Clock()

        # pygame.display.update()
        pygame.event.clear()
        while True:
            event = pygame.event.wait()
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

            screen.fill((128, 0, 128))

            clock.tick(20)
Exemplo n.º 22
0
class Camera:

    def __init__(self, width, height, world, screen=None, top=0, left=0):
        self.height = height
        self.width = width
        self.world = world
        self.max_height = world.end
        self.position = Rect(left, top, width, height)
        self.screen = screen
        self.bar = gui.NarratorBar(Rect(0, 350, self.width, 350))
        self.event_num = 0

        self.bar.set_text("""Hello """ + game.player_name + """!
        Welcome to the world of cubes.
        This world is filled with loneliness.
        A lot of cubes feel lonely and you are no exception.
        How do you overcome this?
        You can move around by using the arrow keys.""")

    def move(self, player_centery):
        if not self.world.player.trying_to_communicate:
            self.position.centery = player_centery

        if self.event_num < len(event_positions):
            if event_positions[self.event_num] >= self.position.top >= event_positions[self.event_num] - 5:
                self.bar.set_text(event_text[self.event_num])
                self.bar.pop_up()
                self.event_num += 1

    def adjust_agent(self, agent):
        return self.adjust_rect(agent.rect)

    def adjust_rect(self, rect):
        new_left = rect.left - self.position.left
        new_top = rect.top - self.position.top
        return Rect(new_left, new_top, rect.width, rect.height)

    def check_visibility(self, rect):
        return self.position.contains(rect)

    def draw(self):
        self.world.background.draw(self.screen, self.position)
        self.draw_overlay(100 - self.world.player.happiness)
        for cluster in self.world.clusters:
            if self.position.top <= cluster.start_position:

                for agent in cluster.members:
                    if self.check_visibility(agent.rect):
                        new_rect = self.adjust_agent(agent)
                        self.screen.blit(agent.s, new_rect.topleft)
                    else:
                        #print "not visible ", self.position.bottom, agent.rect.top, cluster.start_position, cluster.name
                        #print "num members ", len(cluster.members)
                        if agent.rect.top > self.position.bottom:
                            #print "dlkshj"
                            cluster.members.remove(agent)
                            if not cluster.members:
                                self.world.clusters.remove(cluster)
        #new_rect = self.adjust_agent(self.world.player)

        #self.screen.blit(self.world.player.s, new_rect.topleft)

        for agent in self.world.player_cluster.members:
            new_rect = self.adjust_agent(agent)
            self.screen.blit(agent.s, new_rect.topleft)


        self.bar.draw(self.screen)

    def draw_overlay(self, alpha=0):

        s = pygame.Surface((640, 480))  # the size of your rect
        s.set_alpha(alpha)  # alpha level
        s.fill((0, 0, 0))  # this fills the entire surface
        self.screen.blit(s, (0, 0))  # (0,0) are the top-left coordinates
Exemplo n.º 23
0
class PlanetaryOrbitPanel(BaseWidget):
    skippable = True
    skip = False
    current = None
    markers = None
    satellites = None

    curr_digit = 0
    selected_marker = None

    curr_x = 0
    curr_y = 0

    added = None
    visible_markers = True

    def __init__(self, parent):
        super().__init__(parent)
        self.name = 'Planetary Orbit'
        self.image = Surface((ANCHO, ALTO - 32))
        self.image.fill(COLOR_BOX)
        self.rect = self.image.get_rect()
        self.properties = WidgetGroup()
        self.buttons = WidgetGroup()
        self.orbit_descriptions = WidgetGroup()
        self._markers = {}
        self.markers = []
        self.added = []
        self.objects = []
        self.satellites = {}
        self._loaded_orbits = []
        self.area_buttons = self.image.fill(COLOR_AREA,
                                            [0, 420, self.rect.w, 200])
        self.area_markers = Rect(3, 58, 380, 20 * 16)
        self.curr_x = self.area_buttons.x + 3
        self.curr_y = self.area_buttons.y + 21
        self.planet_area = AvailablePlanets(self, ANCHO - 200, 32, 200, 340)
        self.add_orbits_button = SetOrbitButton(self, ANCHO - 94, 394)
        self.area_modify = ModifyArea(self, ANCHO - 201, 374)
        self.show_markers_button = ToggleableButton(self, 'Satellites',
                                                    self.toggle_stellar_orbits,
                                                    3, 421)
        self.show_markers_button.disable()
        self.resonances_button = AddResonanceButton(self, ANCHO - 140, 416)
        self.order_f = self.crear_fuente(14)
        self.write(self.name + ' Panel',
                   self.crear_fuente(16, underline=True),
                   centerx=(ANCHO // 4) * 1.5,
                   y=0)
        self.digit_x = RatioDigit(self, 'x',
                                  self.resonances_button.rect.left - 60,
                                  self.resonances_button.rect.y)
        self.write(':',
                   self.crear_fuente(16),
                   topleft=[
                       self.digit_x.rect.right + 1,
                       self.resonances_button.rect.y - 1
                   ])
        self.digit_y = RatioDigit(self, 'y', self.digit_x.rect.right + 9,
                                  self.resonances_button.rect.y)
        self.ratios = [self.digit_x, self.digit_y]
        self.cycler = cycle(self.ratios)
        next(self.cycler)

        self.properties.add(self.area_modify,
                            self.show_markers_button,
                            self.digit_x,
                            self.digit_y,
                            self.planet_area,
                            self.add_orbits_button,
                            self.resonances_button,
                            layer=2)

        EventHandler.register(self.save_orbits, 'Save')
        EventHandler.register(self.load_orbits, 'LoadData')

    def load_orbits(self, event):
        for position in event.data.get('Planetary Orbits', []):
            if position not in self._loaded_orbits:
                self._loaded_orbits.append(position)

    def set_loaded_orbits(self):
        for orbit_data in self._loaded_orbits:
            a = q(orbit_data['a'], 'earth_radius')
            e = q(orbit_data['e'])
            i = q(orbit_data['i'], 'degree')
            system = Systems.get_system_by_id(orbit_data['star_id'])
            planet = system.get_astrobody_by(orbit_data['planet_id'],
                                             tag_type='id')
            if planet.id not in self.satellites:
                self.satellites[planet.id] = []

            if planet.id not in self._markers:
                self._markers[planet.id] = []
            satellite = system.get_astrobody_by(orbit_data['astrobody'],
                                                tag_type='id')
            self.satellites[planet.id].append(satellite)
            satellite.set_orbit(planet, [a, e, i])
            self.add_existing(satellite, planet.id)

        # borrar las órbitas cargadas para evitar que se dupliquen.
        self._loaded_orbits.clear()

    def save_orbits(self, event):
        orbits = self._loaded_orbits
        for planet_obj in self.planet_area.listed_objects.widgets():
            planet = planet_obj.object_data
            for marker in self._markers.get(planet.id, []):
                if marker.orbit is not None:
                    d = self.create_save_data(marker.orbit)
                    orbits.append(d)

        EventHandler.trigger(event.tipo + 'Data', 'Orbit',
                             {'Planetary Orbits': orbits})

    @staticmethod
    def create_save_data(orb):
        d = {}
        if hasattr(orb, 'semi_major_axis'):
            d['a'] = round(orb.semi_major_axis.m, 2)
        if hasattr(orb, 'inclination'):
            d['i'] = orb.inclination.m
        if hasattr(orb, 'eccentricity'):
            d['e'] = orb.eccentricity.m
        if hasattr(orb, 'astrobody'):
            d['astrobody'] = orb.astrobody.id
            d['planet_id'] = orb.astrobody.parent.id
            d['star_id'] = orb.astrobody.parent.parent.id
        return d

    def toggle_stellar_orbits(self):
        if self.visible_markers:
            self.area_modify.color_alert()
            self.add_orbits_button.disable()
            for marker in self.markers:
                marker.hide()
        else:
            for button in self.buttons.widgets():
                button.deselect()

            self.hide_orbit_types()
            if self.current is not None:
                for marker in self.markers:
                    marker.show()
            self.show_markers_button.disable()
            self.area_modify.color_standby()
        self.visible_markers = not self.visible_markers
        self.area_modify.visible_markers = self.visible_markers

    def hide_orbit_types(self):
        for orbit_type in self.orbit_descriptions.widgets():
            orbit_type.hide()
        for orbit_button in self.buttons.widgets():
            orbit_button.enable()

    def populate(self):
        planet = self.current
        if planet.id not in self._markers:
            self._markers[planet.id] = []
        self.markers = self._markers[planet.id]
        for marker in self.markers:
            if marker not in self.properties:
                self.properties.add(marker, layer=3)
            marker.show()

        self.create_hill_marker(planet)
        self.sort_markers()

    def add_objects(self):
        system = Systems.get_current()
        if system is not None:
            for obj in system.satellites + system.asteroids:
                if obj not in self.objects:
                    self.objects.append(obj)
                    btn = ObjectButton(self, obj, self.curr_x, self.curr_y)
                    if obj.orbit is not None:
                        btn.update_text(obj.orbit.a)
                        markers = self._markers[obj.orbit.star.id]
                        marker_idx = [
                            i for i in range(len(markers))
                            if markers[i].obj == obj
                        ][0]
                        marker = markers[marker_idx]
                        btn.link_marker(marker)

                    self.buttons.add(btn, layer=Systems.get_current_idx())
                    self.properties.add(btn)
            self.sort_buttons()

    def show(self):
        super().show()
        for prop in self.properties.get_widgets_from_layer(2):
            prop.show()
        self.set_loaded_orbits()
        self.add_objects()

    def hide(self):
        super().hide()
        for prop in self.properties.widgets():
            prop.hide()

    def select_planet(self, planet):
        if planet is not self.current:
            self.hide_everything()
            self.current = planet
            self.populate()
            if planet.id not in self.satellites:
                self.satellites[planet.id] = []
        for button in self.buttons.widgets():
            button.enable()
            button.deselect()

        self.visible_markers = True
        sats = self.satellites[planet.id]
        densest = sorted(sats,
                         key=lambda i: i.density.to('earth_density').m,
                         reverse=True)
        if len(densest):
            self.create_roches_marker(densest[0])
        self.sort_markers()

    def select_one(self, button):
        for bttn in self.buttons.widgets():
            bttn.deselect()
        button.select()

    def anchor_maker(self, marker):
        self.area_modify.link(marker)
        self.area_modify.visible_markers = True
        self.add_orbits_button.link(marker)
        self.add_orbits_button.enable()
        self.selected_marker = marker

    def deselect_markers(self, m):
        for marker in self.markers:
            marker.deselect()
            marker.enable()
        m.select()

    def sort_markers(self):
        self.markers.sort(key=lambda m: m.value.m)
        for i, marker in enumerate(self.markers, start=1):
            marker.rect.y = i * 2 * 10 + 38
            if not self.area_markers.contains(marker.rect):
                marker.hide()
            else:
                marker.show()

    def sort_buttons(self):
        x, y = self.curr_x, self.curr_y
        for bt in self.buttons.get_widgets_from_layer(
                Systems.get_current_idx()):
            bt.move(x, y)
            if not self.area_buttons.contains(bt.rect):
                bt.hide()
            else:
                bt.show()
            if x + bt.rect.w + 10 < self.rect.w - bt.rect.w + 10:
                x += bt.rect.w + 10
            else:
                x = 3
                y += 32

    def create_roches_marker(self, obj):
        obj_density = obj.density.to('earth_density').m
        roches = self.current.set_roche(obj_density)
        roches_marker = Marker(self, "Roche's Limit", roches, lock=True)
        first = self.markers[0]
        if first.name == "Roche's Limit":
            self.properties.remove(first)
            self.markers[0] = roches_marker
        else:
            self.markers.append(roches_marker)
        self.properties.add(roches_marker, layer=3)
        return roches

    def create_hill_marker(self, planet):
        x = Marker(self, 'Hill Sphere', planet.hill_sphere)
        x.locked = True
        last = None if not len(self.markers) else self.markers[-1]
        if last is not None and last.name == 'Hill Sphere':
            self.properties.remove(last)
            self.markers[-1] = x
        else:
            self.markers.append(x)
        self.properties.add(x, layer=3)

    def add_new(self, obj):
        if obj not in self.added:
            self.added.append(obj)
        obj_name = obj.cls
        pln_habitable = Systems.get_current().is_habitable(self.current)
        pln_hill = self.current.hill_sphere.m
        obj_type = obj.celestial_type
        roches = self.create_roches_marker(obj)

        text = "A satellite's mass must be less than or equal to the\nmass of the planet."
        text += '\n\nConsider using a less massive satellite for this planet.'
        assert self.current.mass.to('earth_mass').m >= obj.mass.to(
            'earth_mass').m, text

        pos = q(
            round(
                roll(self.current.roches_limit.m,
                     self.current.hill_sphere.m / 2), 3), 'earth_radius')
        orbit = RawOrbit(Systems.get_current_star(), pos)
        obj_marker = Marker(self,
                            obj_name,
                            pos,
                            color=COLOR_SELECTED,
                            lock=False)

        max_value = pln_hill
        if pln_habitable and obj_type != 'asteroid':
            max_value /= 2
        obj_marker.set_max_value(max_value)
        obj_marker.set_min_value(roches.m)
        obj_marker.links(orbit, obj)

        self.markers.append(obj_marker)
        self.properties.add(obj_marker, layer=3)
        self.sort_markers()

        return orbit, obj_marker

    def add_existing(self, obj, pln_id):
        if obj not in self.added:
            self.added.append(obj)
        obj_name = obj.cls
        orbit = obj.orbit
        pos = orbit.a
        obj_marker = Marker(self,
                            obj_name,
                            pos,
                            color=COLOR_SELECTED,
                            lock=False)
        obj_marker.links(orbit, obj)
        self._markers[pln_id].append(obj_marker)

    def hide_markers(self):
        for marker in self.markers:
            marker.hide()
        self.show_markers_button.enable()

    def hide_everything(self):
        for marker in self.markers:
            if marker.linked_button is not None:
                marker.linked_button.hide_info()
            marker.hide()
        self.visible_markers = False
        self.show_markers_button.disable()

    def is_added(self, obj):
        return obj in self.added

    def get_raw_orbit_markers(self):
        raws = [
            m for m in self.markers
            if ((not m.locked) and (type(m.orbit) == RawOrbit))
        ]
        return raws

    def link_satellite_to_planet(self, marker):
        marker._orbit = PseudoOrbit(marker.orbit)
        button = marker.linked_button
        self.hide_everything()
        button.update_text(marker.orbit.a)
        button.info.link_marker(marker)
        button.info.locked = False
        button.info.show()

    def notify(self):
        if not self.visible_markers:
            self.show_markers_button.enable()
            for button in self.buttons.widgets():
                button.disable()

    def get_sorted_satellites(self):
        self.sort_markers()
        markers = [
            marker.obj for marker in self.markers if marker.obj is not None
        ]
        return markers

    def set_current_digit(self, idx):
        self.curr_digit = self.ratios.index(idx)

    def cycle(self):
        has_values = False
        for ratio in self.ratios:
            ratio.deselect()
            has_values = ratio.value != ''

        valid = has_values and self.selected_marker is not None

        if valid:
            self.resonances_button.enable()
        else:
            ratio = next(self.cycler)
            ratio.select()
            WidgetHandler.set_origin(ratio)

    def ratios_to_string(self):
        x = int(self.digit_x.value)
        y = int(self.digit_y.value)
        diff = y - x if y > x else x - y
        self.write('{}° Order'.format(diff),
                   self.order_f,
                   right=self.digit_x.rect.left - 2,
                   y=self.digit_x.rect.y)
        return '{}:{}'.format(x, y)

    def get_difference(self):
        x = int(self.digit_x.value)
        y = int(self.digit_y.value)
        return x - y

    def clear_ratios(self):
        self.digit_x.clear()
        self.digit_y.clear()
Exemplo n.º 24
0
    def query(self, rect: Rect):
        if not self.rect.colliderect(rect):
            return

        yield from (r for r in self.points if rect.contains(r))
        yield from (r for tree in self.children for r in tree.query(rect))