コード例 #1
0
ファイル: rect_test.py プロジェクト: G2ProjectUAV/Project-UAV
 def test_clip(self):
     r1 = Rect(1, 2, 3, 4)
     self.assertEqual(Rect(1, 2, 2, 2), r1.clip(Rect(0, 0, 3, 4)))
     self.assertEqual(Rect(2, 2, 2, 4), r1.clip(Rect(2, 2, 10, 20)))
     self.assertEqual(Rect(2, 3, 1, 2), r1.clip(Rect(2, 3, 1, 2)))
     self.assertEqual((0, 0), r1.clip(20, 30, 5, 6).size)
     self.assertEqual(r1, r1.clip(Rect(r1)), "r1 does not clip an identical rect to itself")
コード例 #2
0
ファイル: rect_test.py プロジェクト: annie60/Xilarius
 def test_clip(self):
     r1 = Rect(1, 2, 3, 4)
     self.assertEqual(Rect(1, 2, 2, 2), r1.clip(Rect(0, 0, 3, 4)))
     self.assertEqual(Rect(2, 2, 2, 4), r1.clip(Rect(2, 2, 10, 20)))
     self.assertEqual(Rect(2, 3, 1, 2), r1.clip(Rect(2, 3, 1, 2)))
     self.assertEqual((0, 0), r1.clip(20, 30, 5, 6).size)
     self.assertEqual(r1, r1.clip(Rect(r1)),
                      "r1 does not clip an identical rect to itself")
コード例 #3
0
 def is_collided(self):
     # Check if the bird touch ground
     if self.bird_height + self.bird_y + 1 >= self.base_y:
         self.distance_reward = 0
         return True
     bird_bbox = Rect(self.bird_x, self.bird_y, self.bird_width,
                      self.bird_height)
     pipe_boxes = []
     for pipe in self.pipes:
         pipe_boxes.append(
             Rect(pipe["x_upper"], pipe["y_upper"], self.pipe_width,
                  self.pipe_height))
         pipe_boxes.append(
             Rect(pipe["x_lower"], pipe["y_lower"], self.pipe_width,
                  self.pipe_height))
         # Check if the bird's bounding box overlaps to the bounding box of any pipe
         if bird_bbox.collidelist(pipe_boxes) == -1:
             return False
         for i in range(2):
             cropped_bbox = bird_bbox.clip(pipe_boxes[i])
             min_x1 = cropped_bbox.x - bird_bbox.x
             min_y1 = cropped_bbox.y - bird_bbox.y
             min_x2 = cropped_bbox.x - pipe_boxes[i].x
             min_y2 = cropped_bbox.y - pipe_boxes[i].y
             if np.any(self.bird_hitmask[
                     self.bird_index][min_x1:min_x1 + cropped_bbox.width,
                                      min_y1:min_y1 + cropped_bbox.height] *
                       self.pipe_hitmask[i][min_x2:min_x2 +
                                            cropped_bbox.width,
                                            min_y2:min_y2 +
                                            cropped_bbox.height]):
                 self.distance_reward = 0.9 / (self.diff_distance() + 1)
                 return True
     return False
コード例 #4
0
ファイル: graphics.py プロジェクト: ikn/wearhouse
 def _update (self, col, row, tile_type_id, tile_rect=None):
     if self._cache_graphic:
         if tile_type_id in self._cache:
             g = self._cache[tile_type_id]
         else:
             g = self._type_to_graphic(tile_type_id)
             self._cache[tile_type_id] = g
     else:
         g = self._type_to_graphic(tile_type_id)
     dest = self._orig_sfc
     if tile_rect is None:
         tile_rect = self.grid.tile_rect(col, row)
     if isinstance(g, (Graphic, pg.Surface, basestring)):
         g = (g,)
     if (g is not None and
         isinstance(g[0], (Graphic, pg.Surface, basestring))):
         sfc = g[0]
         if isinstance(sfc, basestring):
             sfc = self._load_img(sfc)
         elif isinstance(sfc, Graphic):
             sfc = sfc.surface
         if len(g) == 1:
             alignment = rect = None
         else:
             if isinstance(g[1], int) or len(g[1]) == 2:
                 alignment = g[1]
                 rect = None
             else:
                 alignment = None
                 rect = g[1]
             if len(g) == 3:
                 if rect is None:
                     rect = g[2]
                 else:
                     alignment = g[2]
         if alignment is None:
             alignment = 0
         if rect is None:
             rect = sfc.get_rect()
         # clip rect to fit in tile_rect
         dest_rect = Rect(rect)
         dest_rect.center = tile_rect.center
         fit = dest_rect.clip(tile_rect)
         rect = Rect(rect)
         rect.move_ip(fit.x - dest_rect.x, fit.y - dest_rect.y)
         rect.size = dest_rect.size
         # copy rect to tile_rect with alignment
         pos = gameutil.align_rect(rect, tile_rect, alignment)
         dest.blit(sfc, pos, rect)
     else:
         if g is None:
             g = (0, 0, 0, 0)
         # now we have a colour
         dest.fill(gameutil.normalise_colour(g), tile_rect)
     return tile_rect
コード例 #5
0
def push_ip(larger_rect: Rect, smaller_rect: Rect):
    '''Larger rect pushes out smaller rect via the smallest possible vector.'''
    clip = larger_rect.clip(smaller_rect)
    if not clip:
        return
    if clip.height <= clip.width:
        if smaller_rect.centery <= clip.centery:
            smaller_rect.bottom = larger_rect.top
        else:
            smaller_rect.top = larger_rect.bottom
    else:
        if smaller_rect.centerx <= clip.centerx:
            smaller_rect.right = larger_rect.left
        else:
            smaller_rect.left = larger_rect.right
コード例 #6
0
ファイル: pass_map.py プロジェクト: kodo-pp/underkate
    def is_passable(self, rect: pg.Rect) -> bool:
        # TODO: rewrite the algorithm or use JIT/AOT
        # compilation to speed it up in case optimization
        # is required

        clipped = rect.clip(self.image.get_rect())
        if rect != clipped:
            return False

        self.image.lock()
        try:
            for y in range(rect.top, rect.bottom):
                for x in range(rect.left, rect.right):
                    red, *_ = self.image.get_at((x, y))
                    if red == 0:
                        return False
        finally:
            self.image.unlock()

        return True
コード例 #7
0
class BoxCollider(Behaviour):
    def __init__(self):
        super().__init__()
        self.name = "BoxCollider"
        self.is_trigger = False
        self.center = Vector2(0, 0)
        self.offset = Vector2(0, 0)
        self.extent = Vector2(0, 0)
        self.box = Rect(0, 0, 0, 0)
        self.is_debug = False

    def update(self):
        super().update()
        t = self.game_object.get_behaviour("Transform")
        self.center = Vector2(t.position)
        self.center.x += self.offset.x
        self.center.y += self.offset.y
        self.box.center = self.center
        self.box.width = int(self.extent.x)
        self.box.height = int(self.extent.y)

    def render(self):
        super().render()
        if self.is_debug:
            surf = pygame.display.get_surface()
            pygame.draw.rect(surf, (0, 255, 0), self.box, 1)

    #collider-specific methods
    #overlaps() is designed for AABB only
    def overlaps(self, other):
        if isinstance(other, BoxCollider):
            return self.box.colliderect(other.box)

    #WIP
    #prevent_overlap forces the current box away from the other
    def prevent_overlap(self, other):
        if (isintance(other, BoxCollider) and self.box.colliderect(other.box)):
            r = self.box.clip(other.box)
            t = self.game_object.get_behaviour("Transform")
コード例 #8
0
def main():
    pygame.init()
    screen = pygame.display.set_mode((1024, 768))
    pygame.display.set_caption("Rect Test")

    #Create a Rectangle
    #Obs.: will be mouse-controlled
    #optional: create a tuple for the rectangle's colour
    player_rect = Rect(0, 0, 100, 100)
    player_colour = (0, 255, 0)
         
    #Create a list of rectangles
    rect_list = [Rect(550, 100, 200, 200),
                 Rect(150, 150, 350, 350),
                 Rect(800, 600, 150, 150)]

    #optional: create a list of colours (should match rect
    #list length) 
    colours = [(255, 255,   0),
               (255,   0, 255),
               (  0, 255, 255)]

    #Create an extra rectangle for overlap detection
    result = Rect(0, 0, 0, 0)
    
    is_running = True

    #Game loop
    while is_running:
        for evt in pygame.event.get():
            if evt.type == pygame.QUIT:
                is_running = False

        #Controlling the player rectangle with the mouse
        #(uncomment code below)
        player_rect.center = pygame.mouse.get_pos()

        #clip result rectangle:
        #result = player_rect.clip(rect_list[0])
        #advanced: clip against a list
        result = player_rect.clip(rect_list[player_rect.collidelist(rect_list)])

        #Render part
        screen.fill((0, 0, 127))

        #Render rectangles:
        #1: Render player rectangle
        pygame.draw.rect(screen, player_colour, player_rect)

        #2: Render list of rectangles
        #optional: use a for loop to render them with the
        #same or different colours. If using a for loop, the
        #example code below should be adjusted accordingly
        for i in range(len(rect_list)):            
            pygame.draw.rect(screen, colours[i], rect_list[i])

        #If there is a collision, render it here
        #Alternative if statements:
        #if player_rect.collidelist(rect_list) > -1:
        #if result.width > 0 and result.height > 0:
        if result.width > 0 < result.height:
            pygame.draw.rect(screen, (255, 0, 0), result, 5)

        #Render loop end
        pygame.display.flip()

    #cleanup
    pygame.quit()
    sys.exit()
コード例 #9
0
ファイル: base.py プロジェクト: spartrekus/freevo1
class BaseAnimation:
    """
    Base class for animations, this should perhaps be changed to use sprites
    in the future (if one decides to go with a RenderGroup model)

    @cvar background: Surface Background (screen)
    @cvar surface   : The Surface obj. to work with
    @cvar active    : Should it be updated in the poll
    @cvar delete    : Delete from list on next poll
    @cvar updates   : list of updates from screen
    @cvar next_updat: timestamp for next update
    """

    background   = None   # Surface Background (screen)
    surface      = None   # The Surface obj. to work with
    active       = False  # Should it be updated in the poll
    delete       = False  # Delete from list on next poll
    updates      = []     # list of updates from screen
    next_update  = 0      # timestamp for next update


    def __init__(self, rectstyle, fps=20, bg_update=True, bg_wait=False, bg_redraw=False):
        """
        Initialise an instance of BaseAnimation

        @ivar rectstyle : the rectangle defining the position on the screen (pygame)
        @ivar fps       : Desired fps
        @ivar bg_update : update the animation with background from screen
        @ivar bg_wait   : initially wait for updated background before activating
        @ivar bg_redraw : set background to original screen bg when finished
        """
        logger.log( 9, '__init__(rectstyle=%r, fps=%r, bg_update=%r, bg_wait=%r, bg_redraw=%r)', rectstyle, fps, bg_update, bg_wait, bg_redraw)


        self.rect      = Rect(rectstyle)
        self.bg_update = bg_update
        self.bg_wait   = bg_wait
        self.bg_redraw = bg_redraw

        self.surface = Surface((self.rect.width, self.rect.height)).convert()

        self.set_fps(fps)


    def get_surface(self, width, height):
        """ Helper for creating surfaces """
        logger.log( 9, 'get_surface(width=%r, height=%r)', width, height)
        return Surface( (width, height), 0, 32)


    def get_osd(self):
        """ Helper for getting osd singleton """
        logger.log( 9, 'get_osd()')
        return osd.get_singleton()


    def set_fps(self, fps):
        """ Sets the desired fps """
        logger.log( 9, 'set_fps(fps=%r)', fps)
        self.interval  = int(1000.0/float(fps))


    def set_screen_background(self):
        """ Update the background """
        logger.log( 9, 'set_screen_background()')
        if not self.background:
            self.background = osd.get_singleton().getsurface(rect=self.rect)
            self.updates = []

        elif len(self.updates) > 0:

            # find the topleft corner
            x = self.rect.right
            y = self.rect.bottom
            for i in self.updates:
                x = min(x, i.left)
                y = min(y, i.top)

            # find the total rect of the collisions
            upd = Rect(x, y, 0, 0)
            upd.unionall_ip(self.updates)
            self.updates = []

            x      = upd[0] - self.rect.left
            y      = upd[1] - self.rect.top
            bg_tmp = osd.get_singleton().getsurface(rect=upd)

            self.background.blit(bg_tmp, (x, y))

        self.surface.blit(self.background, (0,0))


    def get_rect(self):
        """ Get the rectangle of the current object
        @returns: the rectangle tuple
        """
        logger.log( 9, 'get_rect()')
        return self.rect


    def start(self):
        """ Starts the animation """
        logger.log( 9, 'start()')
        render.get_singleton().add_animation(self)
        if not self.bg_wait:
            self.active = True


    def stop(self):
        """ Stops the animation from being polled """
        logger.log( 9, 'stop()')
        self.active = False


    def remove(self):
        """ Flags the animation to be removed from the animation list """
        logger.log( 9, 'remove()')
        self.active = False

        # set the org. bg if we use this
        if self.bg_update:
            osd.get_singleton().putsurface(self.background, self.rect.left, self.rect.top)
            osd.get_singleton().update([self.rect])

        self.delete = True


    def damage(self, rectstyles=[]):
        """ Checks if the screen background has been damaged

        @note: If the rect passed damages our rect, but no actual blit is done
        on osd.screen, we'll end up with a copy of our animation in our bg. This is BAD.
        """
        logger.log( 9, 'damage(rectstyles=%r)', rectstyles)
        if not (self.bg_redraw or self.bg_update) or rectstyles == None:
            return

        for rect in rectstyles:
            if rect == None:
                continue

            if self.rect.colliderect(rect):
                if self.bg_wait:
                    self.active = True

                self.updates.append(self.rect.clip(rect))
                logger.debug('Damaged, updating background')


    def poll(self, current_time):
        """ Poll the animations """
        logger.log( 9, 'poll(current_time=%r)', current_time)
        if self.next_update < current_time:
            self.next_update = current_time + self.interval

            if self.bg_update:
                self.set_screen_background()

            self.draw()
            return self.rect, self.surface


    def draw(self):
        """ Overload to do stuff with the surface """
        logger.log( 9, 'draw()')
        pass
コード例 #10
0
class BoxCollider(Behaviour):
    def __init__(self):
        super().__init__()
        self.name = "BoxCollider"
        self.is_trigger = False
        self.center = Vector2(0, 0)
        self.offset = Vector2(0, 0)
        self.extent = Vector2(0, 0)
        self.box = Rect(0, 0, 0, 0)
        self.is_debug = False

    def start(self):
        super().start()
        t = self.game_object.get_behaviour("Transform")
        self.center = Vector2(t.position)
        self.center.x += self.offset.x
        self.center.y += self.offset.y
        self.box.center = self.center
        self.box.width = int(self.extent.x)
        self.box.height = int(self.extent.y)

    def update(self):
        super().update()
        #Code repeated to account for runtime collider changes
        t = self.game_object.get_behaviour("Transform")
        self.center = Vector2(t.position)
        self.center.x += self.offset.x
        self.center.y += self.offset.y
        self.box.center = self.center
        self.box.width = int(self.extent.x)
        self.box.height = int(self.extent.y)

    def render(self):
        super().render()
        if self.is_debug:
            surf = pygame.display.get_surface()
            pygame.draw.rect(surf, (0, 255, 0), self.box, 1)

    #collider-specific methods
    #overlaps() is designed for AABB only
    def overlaps(self, other):
        if isinstance(other, BoxCollider):
            return self.box.colliderect(other.box)

    #WIP
    #prevent_overlap forces the current box away from the other
    def prevent_overlap(self, other):
        if (isinstance(other, BoxCollider)
                and self.box.colliderect(other.box)):
            o = other.game_object.get_behaviour("Transform")
            r = self.box.clip(other.box)
            t = self.game_object.get_behaviour("Transform")

            ###################################################
            #Solution: Check for the smallest axis overlap and#
            #displace the invoking object's collider box back #
            #along it.                                        #
            #Obs.: This prevents overlap, but still causes a  #
            #small penetration depth due to the ship's speed. #
            #More elaborate calculations will probably be     #
            #needed, but the current approach should suffice  #
            #for the intended objective.                      #
            ###################################################

            if (r.width < r.height):
                #if the other is to the right, push back to the left
                if (o.position.x >= t.position.x):
                    t.position.x -= (r.width + 1)
                else:
                    t.position.x += (r.width + 1)
            else:
                #if the other is below, push it up
                if (o.position.x >= t.position.y):
                    t.position.y -= (r.height + 1)
                else:
                    t.position.y += (r.height + 1)
コード例 #11
0
ファイル: box_collider.py プロジェクト: HerculesDC/MultiGame
class BoxCollider(Collider):
    def __init__(self, debug=False, size_=(0, 0)):
        super().__init__("BoxCollider", debug)
        self.center = None
        self.rotation = None
        self.size = size_
        self.rect = Rect((0, 0), self.size)

    def start(self):
        super().start()

    def update(self, delta):
        super().update(delta)
        self.rect.center = self.center

    def render(self):
        super().render()
        if self._is_debug and self.size and self.center:
            import pygame.draw
            from engine.game_env import Game
            pygame.draw.rect(Game.instance.get_screen(), (0, 255, 0),
                             self.rect, 1)

    def collidepoint(self, other):
        super().collidepoint(other)
        return self.rect.collidepoint(other.center)

    def colliderect(self, other):
        super().colliderect(other)
        return self.rect.colliderect(other.rect)

    def get_clip_area(self, other):
        return self.rect.clip(other.rect)

    def collideline(self, other):
        super().collideline(other)
        #REDO!!! This only works in pygame 2.0
        return False

    def collidecircle(self, other):
        super().collidecircle(other)
        #BUGGY!!! VERIFY
        test_x = other.center[0]
        test_y = other.center[1]

        if other.center[0] < self.rect.left:
            test_x = self.rect.left
        elif other.center[0] > self.rect.right:
            test_x = self.rect.right

        if other.center[1] < self.rect.top:
            test_y = self.rect.top
        elif other.center[1] > self.rect.bottom:
            test_y = self.rect.bottom

        dist_x = other.center[0] - test_x
        dist_y = other.center[1] - test_y

        dist = ((dist_x * dist_x) + (dist_y * dist_y))**0.5

        return dist <= other.radius
コード例 #12
0
    def draw(self, surface, bgd=None):
        """
        Draws all sprites on the surface you pass in.
        You can pass the background too. If a background is already set, 
        then the bgd argument has no effect.
        """
        # speedups
        _orig_clip = surface.get_clip()
        _clip = self._clip
        if _clip is None:
            _clip = _orig_clip

        _surf = surface
        _sprites = self._spritelist
        _old_rect = self.spritedict
        _update = self.lostsprites
        _update_append = _update.append
        _ret = None
        _surf_blit = _surf.blit
        _rect = pygame.Rect
        if bgd is not None:
            self._bgd = bgd
        _bgd = self._bgd

        _surf.set_clip(_clip)
        # -------
        # 0. deside if normal render of flip
        start_time = get_ticks()
        if self._use_update:  # dirty rects mode
            # 1. find dirty area on screen and put the rects into _update
            # still not happy with that part
            for spr in _sprites:
                if 0 < spr.dirty:
                    if spr.source_rect is not None:
                        _union_rect = Rect(spr.rect.topleft,
                                           spr.source_rect.size)
                    else:
                        _union_rect = _rect(spr.rect)
                    _union_rect_collidelist = _union_rect.collidelist
                    _union_rect_union_ip = _union_rect.union_ip
                    i = _union_rect_collidelist(_update)
                    while -1 < i:
                        _union_rect_union_ip(_update[i])
                        del _update[i]
                        i = _union_rect_collidelist(_update)
                    _update_append(_union_rect.clip(_clip))

                    _union_rect = _rect(_old_rect[spr])
                    _union_rect_collidelist = _union_rect.collidelist
                    _union_rect_union_ip = _union_rect.union_ip
                    i = _union_rect_collidelist(_update)
                    while -1 < i:
                        _union_rect_union_ip(_update[i])
                        del _update[i]
                        i = _union_rect_collidelist(_update)
                    _update_append(_union_rect.clip(_clip))
            # can it be done better? because that is an O(n**2) algorithm in
            # worst case

            # clear using background
            if _bgd is not None:
                for rec in _update:
                    _surf_blit(_bgd, rec, rec)

            # 2. draw
            for spr in _sprites:
                if 1 > spr.dirty:
                    if spr._visible:
                        # sprite not dirty, blit only the intersecting part
                        if spr.source_rect is not None:
                            _spr_rect = Rect(spr.rect.topleft,
                                             spr.source_rect.size)
                        else:
                            _spr_rect = spr.rect
                        _spr_rect_clip = _spr_rect.clip
                        for idx in _spr_rect.collidelistall(_update):
                            # clip
                            clip = _spr_rect_clip(_update[idx])
                            _surf_blit(spr.image, clip, \
                                       (clip[0]-_spr_rect[0], \
                                            clip[1]-_spr_rect[1], \
                                            clip[2], \
                                            clip[3]))#, spr.blendmode)
                else:  # dirty sprite
                    if spr._visible:
                        if spr.source_rect is not None:
                            _old_rect[spr] = _surf_blit(spr.image, spr.rect, \
                                               spr.source_rect)#, spr.blendmode)
                        else:
                            _old_rect[spr] = _surf_blit(spr.image, spr.rect)

                    if spr.dirty == 1:
                        spr.dirty = 0
            _ret = list(_update)
        else:  # flip, full screen mode
            if _bgd is not None:
                _surf_blit(_bgd, (0, 0))
            for spr in _sprites:
                if spr.visible:
                    if spr.source_rect is not None:
                        _old_rect[spr] = _surf_blit(
                            spr.image, spr.rect,
                            spr.source_rect)  #,spr.blendmode)
                    else:
                        _old_rect[spr] = _surf_blit(
                            spr.image,
                            spr.rect)  #, spr.source_rect)#,spr.blendmode)
            _ret = [_rect(_clip)]  # return only the part of the screen changed

        # timing for switching modes
        # how to find a good treshold? it depends on the hardware it runs on
        end_time = get_ticks()
        if end_time - start_time > self._time_threshold:
            self._use_update = False
        else:
            self._use_update = True

##        # debug
##        print "               check: using dirty rects:", self._use_update

# emtpy dirty reas list
        _update[:] = []

        # -------
        # restore original clip
        _surf.set_clip(_orig_clip)
        return _ret