예제 #1
0
class TextElement(Sprite):
    def __init__(self, text, sx, sy, w=-1, h=-1):
        Sprite.__init__(self)
        self.sx = sx
        self.sy = sy
        self.w = w
        self.h = h
        self.setText(text)
    
    def setText(self, text):
        self.text = text
        dims = getSurfaceDimsFromText(text, TileService.size, self.w, self.h)
        print('text dims', dims)
        print('sx', self.sx, 'sy', self.sy)
        self.image = Surface(dims)
        self.rect = (
            self.sx,
            self.sy,
            dims[0],
            dims[1]
        )
        blits = []
        x = 0
        y = 0
        for char in self.text:
            blits.append((TileService.getTileByChar(char), (x, y)))
            x += TileService.size
        self.image.blits(blit_sequence=blits)
예제 #2
0
 def update_power(self, screen: pygame.Surface, val):
     self.power_viewer.fill(col_screen)
     self.power_text = self.font_param.render(str(val), True, col_text_white, col_screen)
     screen.blits(((self.power_viewer, self.power_viewer_rect), (self.power_text, self.power_text_rect)), 0)
     # redraw power bar fill
     pygame.draw.rect(screen, col_screen, (self.fill_x, self.fill_y, self.fill_w, self.fill_h))
     self.power_bar_fill_rect = pygame.draw.rect(screen, col_power, (self.fill_x, self.fill_y, self.fill_w * (val / 100), self.fill_h))
예제 #3
0
    def scroll_text(self, text) -> None:
        """Fills the main screen with black and rolls up
        the passed text. font and size are hardcoded
        
        NOTE: for now when passing a long text, lines shouldn't be longer than `43` characters
        or the text will be cut. this is due to the fact that I wanted the textbox to be only 2/3
        of the window's width

        Parameters
        ----------
        text -> text to be scrolled up

        Tests
        -----
        - passing a very long text
        - passing a text with very long lines
        - passing text with escapeable chars
        """

        splitted = text.splitlines()
        self.screen.fill(BLACK)
        complete_surface = Surface((WIDTH * 2 // 3, 30 * len(splitted)))
        text_lines = []
        for index, line in enumerate(splitted):
            line = line.strip()
            text_surface, text_surface_rect = self.draw_text(
                line,
                32, (WHITE, RED),
                x=0,
                y=32 * index,
                surface=complete_surface)
            text_lines.append((text_surface, text_surface_rect))

        complete_surface_rect = complete_surface.get_rect()
        complete_surface_rect.topleft = (WIDTH // 6, HEIGHT)

        waiting = True
        # while the bot of the text surface has not reached the top of screen
        while waiting and complete_surface_rect.bottom > 0:
            # scroll text up
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    waiting = False
                    self.running = False
                if event.type == pg.KEYUP:
                    waiting = False

            self.clock.tick(60)
            complete_surface_rect.y -= 1
            complete_surface.blits(text_lines, False)
            self.screen.blit(complete_surface, complete_surface_rect)
            pg.display.flip()
예제 #4
0
    def __init__(self, scene, location: Tuple[int, int], font_path, word, size: int, frame_length: int = 60):
        self.frame_length = frame_length
        self.frame_count = 0
        self.angle = 0.0
        self.zoom = 1.0

        self.sound = pygame.mixer.Sound(str(Paths.sfx / "explosion.ogg"))
        self.sound.play()

        explosion_sets = (
            ("explosion-blue.png", Colors.orange),
            ("explosion-orange.png", Colors.blue),
            ("explosion-yellow.png", Colors.red),
            ("explosion-red.png", Colors.yellow)
        )

        filename, color = random.choice(explosion_sets)
        explosion_image: Surface = pygame.image.load(str(Paths.effects / filename))
        explosion_font_size: int = 26 - (len(word) - 5)
        explosion_font: Font = Font(str(font_path), explosion_font_size)
        explosion_text: Surface = explosion_font.render(word, True, color)

        explosion_image = pygame.transform.smoothscale(explosion_image, (size, size))

        # Turn around after x frames
        surface = Surface((size, size))
        surface.fill(Colors.black)
        surface.set_colorkey(Colors.black)
        surface.blits(
            (
                (explosion_image, (0, 0)),
                (
                    explosion_text,
                    (
                        (explosion_image.get_width() / 2) - explosion_text.get_width() / 2,
                        (explosion_image.get_height() / 2) - explosion_text.get_height() / 2
                    )
                )
            )
        )

        super().__init__(scene, location, surface)
예제 #5
0
 def draw(self, surface: Surface) -> None:
     sprites = self.sprites()
     if hasattr(surface, "blits"):
         self.spritedict.update(
             zip(
                 sprites,
                 surface.blits((spr.image, spr.rect.move(self.camera_rect))
                               for spr in sprites)))
     else:
         for spr in sprites:
             self.spritedict[spr] = surface.blit(spr.image, spr.rect)
     self.lostsprites = []
예제 #6
0
 def update_angle(self, screen: pygame.Surface, val):
     self.angle_viewer.fill(col_screen)
     self.angle_text = self.font_param.render(str(val), True, col_text_white, col_screen)
     screen.blits(((self.angle_viewer, self.angle_viewer_rect), (self.angle_text, self.angle_text_rect)), 0)
예제 #7
0
    def __init__(self, screen: pygame.Surface, cpl_x, cpl_y, cpl_w, cpl_h, control_scale):

        control_img = pygame.image.load("../resources/images/control_panel.png").convert()
        self.surf = pygame.transform.scale(control_img, (cpl_w, cpl_h))
        self.rect = self.surf.get_rect()
        self.rect.x = cpl_x
        self.rect.y = cpl_y
        screen.blit(self.surf, (cpl_x, cpl_y))

        # add and draw control elements


        '''sec_w = cpl_w / 5
        wp_x = sec_w
        angle_x = sec_w * 2
        power_x = sec_w * 3
        fire_x = sec_w * 4 '''

        w1 = cpl_w / 5
        rw = cpl_w - w1
        sec_w = rw / 5
        wp_x = w1
        angle_x = w1 + sec_w
        power_x = w1 + sec_w * 2
        fire_x = w1 + sec_w * 3

        control_baseline_y = self.rect.y + self.rect.h * 0.45  # setting up a y-axis center line for controls

        # create surfaces

        wp_img = pygame.image.load("../resources/images/wp_list.png")
        angle_img = pygame.image.load("../resources/images/param_window.png")
        angle_dec_img = pygame.image.load("../resources/images/inc_button.png")
        angle_inc_img = pygame.image.load("../resources/images/dec_button.png")
        power_img = pygame.image.load("../resources/images/param_window.png")
        power_bar_img = pygame.image.load("../resources/images/power_bar.png")
        power_inc_img = pygame.image.load("../resources/images/inc_button.png")
        power_dec_img = pygame.image.load("../resources/images/dec_button.png")
        fire_img = pygame.image.load("../resources/images/param_window.png")
        fire_text_img = pygame.image.load("../resources/images/fire_text.png")
        scoreboard_frame = pygame.image.load("../resources/images/scoreboard_frame.png")

        # scale surfaces

        wp_surf = scale(wp_img, control_scale)
        angle_inc_surf = scale(angle_inc_img, control_scale)
        angle_surf = scale(angle_img, control_scale)
        angle_dec_surf = scale(angle_dec_img, control_scale)
        power_dec_surf = scale(power_dec_img, control_scale)
        power_surf = scale(power_img, control_scale)
        power_inc_surf = scale(power_inc_img, control_scale)
        power_bar_surf = scale(power_bar_img, control_scale)
        fire_surf = scale(fire_img, control_scale)
        fire_text_surf = scale(fire_text_img, control_scale / 1.2)
        scoreboard_frame_surf = scale(scoreboard_frame, control_scale)

        # get rects with simple names

        self.wp = wp_surf.get_rect()
        self.angle_inc = angle_inc_surf.get_rect()
        self.angle_sel = angle_surf.get_rect()
        self.angle_dec = angle_dec_surf.get_rect()
        self.power_dec = power_dec_surf.get_rect()
        self.power = power_surf.get_rect()
        self.power_inc = power_inc_surf.get_rect()
        self.power_bar = power_bar_surf.get_rect()
        self.fire = fire_surf.get_rect()
        self.fire_text = fire_text_surf.get_rect()
        self.scoreboard = scoreboard_frame_surf.get_rect()

        # set positions

        self.wp.center = (wp_x + angle_x) / 2, control_baseline_y
        self.angle_sel.center = (angle_x + power_x) / 2, control_baseline_y
        self.power.center = (power_x + fire_x) / 2, control_baseline_y
        # self.power_bar.center = (power_x + fire_x) / 2, (control_baseline_y + self.rect.bottom) / 2
        # The 0.995 to place bar is irritating; need to fix
        self.power_bar.center = (power_x + fire_x) / 2, 0.995*(self.power.bottom + self.rect.bottom) / 2
        self.angle_inc.center = ((angle_x + power_x) / 2) - self.angle_inc.w / 4 - self.angle_sel.w / 2, control_baseline_y
        self.angle_dec.center = ((angle_x + power_x) / 2) + self.angle_dec.w / 4 + self.angle_sel.w / 2, control_baseline_y
        self.power_dec.center = ((power_x + fire_x) / 2) - self.power_dec.w / 4 - self.power.w / 2, control_baseline_y
        self.power_inc.center = ((power_x + fire_x) / 2) + self.power_inc.w / 4 + self.power.w / 2, control_baseline_y
        self.fire.center = (fire_x + (fire_x + sec_w)) / 2, (self.rect.y + self.rect.h / 2)
        self.fire_text.center = self.fire.center
        self.scoreboard.center = (self.fire.centerx + sec_w, self.rect.centery)

        # control windows

        self.wp_viewer = pygame.Surface((int(self.wp.w * 0.8), int(self.wp.h * 0.6)))
        self.wp_viewer_rect = self.wp_viewer.get_rect()
        self.wp_viewer.fill(col_screen)
        self.wp_viewer_rect.center = self.wp.center

        self.angle_viewer = pygame.Surface((int(self.angle_sel.w * 0.65), int(self.angle_sel.h * 0.6)))
        self.angle_viewer_rect = self.angle_viewer.get_rect()
        self.angle_viewer.fill(col_screen)
        self.angle_viewer_rect.center = self.angle_sel.center

        self.power_viewer = pygame.Surface((int(self.power.w * 0.65), int(self.power.h * 0.6)))
        self.power_viewer_rect = self.power_viewer.get_rect()
        self.power_viewer.fill(col_screen)
        self.power_viewer_rect.center = self.power.center

        self.power_bar_viewer = pygame.Surface((int(self.power_bar.w * 0.8), int(self.power_bar.h * 0.6)))
        self.power_bar_viewer_rect = self.power_bar_viewer.get_rect()
        self.power_bar_viewer_rect.center = self.power_bar.center
        self.power_bar_viewer.fill(col_screen)

        self.score_viewer = pygame.Surface((int(self.scoreboard.w * 0.8), int(self.scoreboard.h * 0.76)))
        self.score_viewer_rect = self.score_viewer.get_rect()
        self.score_viewer_rect.center = (self.scoreboard.centerx + 1, self.scoreboard.centery + 1)
        self.score_viewer.fill(col_screen)

        # scoreboard_surf.fill(col_screen)

        # fill area max size and loc

        self.fill_w = int(self.power_bar.w * 0.78)
        self.fill_h = int(self.power_bar.h * 0.44)
        self.fill_x = int(self.power_bar_viewer_rect.x + (self.power_bar_viewer_rect.w - self.fill_w) / 2)
        self.fill_y = int(self.power_bar_viewer_rect.y + (self.power_bar_viewer_rect.h - self.fill_h) / 2)
        self.power_bar_fill_area = pygame.Rect(self.fill_x, self.fill_y, self.fill_w, self.fill_h)  # max area

        # display text
        # self.font_param = pygame.font.SysFont("segoeui", 13, True)
        self.font_param = pygame.font.Font("../resources/fonts/expressway.ttf", 13)
        # self.font_heading = pygame.font.SysFont("comicsansms", 16, True)
        self.font_heading = pygame.font.Font("../resources/fonts/expressway.ttf", 15)

        self.angle_text = self.font_param.render(str(default_angle_val), True, col_text_white, col_screen)
        self.angle_text_rect = self.angle_text.get_rect()
        self.angle_text_rect.center = self.angle_viewer_rect.center

        self.angle_heading = self.font_heading.render("Angle", True, col_text_white)
        self.angle_heading_rect = self.angle_heading.get_rect()
        self.angle_heading_rect.center = (self.angle_viewer_rect.centerx, (self.angle_viewer_rect.top + self.rect.top) / 2)

        self.power_text = self.font_param.render(str(default_power_val), True, col_text_white, col_screen)
        self.power_text_rect = self.power_text.get_rect()
        self.power_text_rect.center = self.power_viewer_rect.center

        self.power_heading = self.font_heading.render("Power", True, col_text_white)
        self.power_heading_rect = self.power_heading.get_rect()
        self.power_heading_rect.center = (self.power_viewer_rect.centerx, (self.power_viewer_rect.top + self.rect.top) / 2)

        self.wp_text = self.font_param.render("Plain ammo", True, col_text_white, col_screen)
        self.wp_text_rect = self.wp_text.get_rect()
        self.wp_text_rect.center = self.wp_viewer_rect.center

        self.wp_heading = self.font_heading.render("Weapon", True, col_text_white)
        self.wp_heading_rect = self.wp_heading.get_rect()
        self.wp_heading_rect.center = (self.wp_viewer_rect.centerx, (self.wp_viewer_rect.top + self.rect.top) / 2)

        self.scoreboard_heading = self.font_param.render("Scoreboard", True, col_text_white)
        self.scoreboard_heading_rect = self.scoreboard_heading.get_rect()
        self.scoreboard_heading_rect.center = (self.score_viewer_rect.centerx, self.score_viewer_rect.top + self.score_viewer_rect.h / 9)

        '''self.fire_text = self.font.render("Fire", True, col_fire)
        self.fire_text_rect = self.fire_text.get_rect()
        self.fire_text_rect.center = self.fire.center'''


        # draw control elements

        screen.blits(((wp_surf, self.wp), (angle_surf, self.angle_sel), (power_surf, self.power),
                      (power_bar_surf, self.power_bar),
                      (fire_surf, self.fire),
                      (angle_dec_surf, self.angle_dec),
                      (angle_inc_surf, self.angle_inc),
                      (power_inc_surf, self.power_inc),
                      (power_dec_surf, self.power_dec),
                      (self.wp_viewer, self.wp_viewer_rect),
                      (self.angle_viewer, self.angle_viewer_rect),
                      (self.power_viewer, self.power_viewer_rect),
                      (self.power_bar_viewer, self.power_bar_viewer_rect),
                      # (self.power_bar_fill, self.power_bar_fill_rect),
                      (self.angle_text, self.angle_text_rect),
                      (self.power_text, self.power_text_rect),
                      (self.wp_text, self.wp_text_rect),
                      # (self.fire_text, self.fire_text_rect)
                      (self.angle_heading, self.angle_heading_rect),
                      (self.power_heading, self.power_heading_rect),
                      (self.wp_heading, self.wp_heading_rect),
                      (fire_text_surf, self.fire_text),
                      (scoreboard_frame_surf, self.scoreboard),
                      (self.score_viewer, self.score_viewer_rect),
                      (self.scoreboard_heading, self.scoreboard_heading_rect)
                      ), 0)

        # fill bar at the end
        self.power_bar_fill_rect = pygame.draw.rect(screen, col_power,
                                                    (self.fill_x, self.fill_y,
                                                     int(self.fill_w * (default_power_val / 100)),
                                                     self.fill_h))
예제 #8
0
class Board:
    squares = []

    def __init__(self, size):
        self.size = (size, size)
        self.sq_size = int(self.size[1] / 8)
        self.surface = Surface(self.size)

    def within(self, pos):
        return pos[0] < self.size[0] and pos[1] < self.size[1]

    def clear(self):
        for row in self.squares:
            for sq in row:
                sq.fresh = False
                sq.hover = False

    def square(self, pos=None, query=None):
        squar = None
        if (pos):
            point = lambda i: floor(pos[i] / self.sq_size)
            squar = self.squares[(int)(point(1))][(int)(point(0))]
        if (query):
            match = True
            for k, v in query.items():
                if (squar):
                    match = v and getattr(squar, k)
                else:
                    for rank in self.squares:
                        for sq in rank:
                            squar = sq if v and getattr(sq, k) else None
                            if (squar):
                                break
                        if (squar):
                            break

            squar = squar if match else None
        return squar

    def update(self):
        for row in self.squares:
            row_blits = []
            for sq in row:
                if (not sq.fresh):
                    sq.draw()
                row_blits.append((sq.surface, (sq.x, sq.y)))
            self.surface.blits(row_blits)
        return self.surface

    def draw(self, square=None):
        sq_pad = 8
        font_size = 14

        fen_model = fromFEN(START_BOARD)

        if (len(self.squares) == 0):
            for r in range(0, len(fen_model)):
                rank = fen_model[r]
                row = []
                for s in range(0, len(rank)):
                    sq = rank[s]
                    _x = sq['_x']
                    _y = sq['_y']
                    tx = self.sq_size * _x
                    ty = self.sq_size * _y
                    toggle_color = is_even(_x + 1) ^ is_even(_y + 1)

                    sq_piece = None
                    if (sq['piece']):
                        sq_piece = Piece({
                            '_x': _x,
                            '_y': _y,
                            'x': tx,
                            'y': ty,
                            'size': self.sq_size - (sq_pad * 2),
                            'role': sq['piece']['role'],
                            'color': sq['piece']['color'],
                            'path': []
                        })
                    square = Square({
                        'size':
                        self.sq_size,
                        '_x':
                        _x,
                        '_y':
                        _y,
                        'x':
                        tx,
                        'y':
                        ty,
                        'pad':
                        sq_pad,
                        'font_size':
                        font_size,
                        'piece':
                        sq_piece,
                        'color':
                        DARK if toggle_color else LIGHT,
                        'text_color':
                        LIGHT if toggle_color else DARK,
                        'label':
                        str(chr(73 - (_y + 1))) + str(_x + 1),
                        'file':
                        str(_x + 1) if _y == 7 else None,
                        'rank':
                        str(chr(73 - (_y + 1))) if _x == 0 else None,
                        'settings': {
                            'draw_coords': False,
                            'draw_rankfile': True
                        }
                    })
                    square.draw()
                    row.append(square)
                self.squares.append(row)
                row_blits = list(map(lambda s: (s.surface, (s.x, s.y)), row))
                self.surface.blits(row_blits)

        return self.surface
예제 #9
0
class Visualizer:
    def __init__(self, verbose):
        self._verbose = verbose

    def _print(self, *args):
        if self._verbose:
            print(*args)

    def init(self, source_path):
        self._source_file = open(source_path, 'r')

        self._print('init')
        self._iteration = 0
        self._last_update_time = datetime.now()
        self._paused = False

        pygame.init()
        self._init_flyweights()

        first_frame = self._read_frame()
        if first_frame['eof']:
            raise Exception('Empty grid-viz file')
        self._last_frame = first_frame

        self._goals = first_frame['goals']

        self._grid_surface = Surface(first_frame['frame_size'])
        self._screen_size = self._get_screen_size(first_frame['frame_size'])

        self._print('screen size:', self._screen_size)

        # font / text init
        self._iteration_msg_location = (SCREEN_PADDING, SCREEN_PADDING +
                                        self._grid_surface.get_size()[1] + 3)

        self._title_font = font.SysFont(None, 30)
        self._small_msg_font = font.SysFont(None, 12)

        # pre-render first frame onto grid surface
        self._render_frame(first_frame)

    def render_title_screen(self):
        if self._source_file is None:
            raise Exception('Visualizer not initialized')

        screen = display.set_mode(self._screen_size)
        txt_img = self._title_font.render('Press ENTER to start', True, WHITE)

        screen.blit(txt_img, (20, 20))
        display.update()

        if not self._get_continue_signal():
            self.quit()
            return False

        self._show_grid()
        return True

    def next_frame(self, speed, single_frame=False):
        self._print('In next frame')
        now = datetime.now()
        ms_since_update = timedelta_to_milliseconds(now -
                                                    self._last_update_time)

        if ms_since_update < speed:
            self._print('sleeping for', speed - ms_since_update, 'ms')
            sleep((speed - ms_since_update) / 1000)

        for evt in event.get():
            if evt.type == pygame.QUIT:
                self._print('Quit event')
                self.quit()
                return False

            if evt.type == pygame.KEYUP:
                # toggle pause
                if evt.key == pygame.K_p:
                    self._print('p pressed')
                    self._paused = not self._paused

                # enter always unpauses if applicable
                if evt.key == pygame.K_RETURN or evt.key == pygame.K_KP_ENTER:
                    self._print('return pressed')
                    self._paused = False

        self._print('event queue flushed')

        # paused, so go away
        if self._paused:
            self._print('Paused')
            return True

        self._iteration += 1
        frame = self._read_frame()
        if frame['eof']:
            self._print('Finished reading file')
            self._render_finished_msg()
            return False
        self._last_frame = frame

        self._render_frame(frame)
        self._show_grid()

        if single_frame:
            self._paused = True

        return True

    def quit(self, wait_for_signal=False):
        if wait_for_signal:
            self._print('Waiting for shutdown signal')
            self._get_continue_signal()

        self._print('Shutting down visualizer')
        display.quit()
        self._source_file.close()
        self._source_file = None

    def _init_flyweights(self):
        full_cell_rect = Rect(0, 0, CELL_SIZE, CELL_SIZE)

        obstacle = Surface((CELL_SIZE, CELL_SIZE))
        draw.rect(obstacle, OBSTACLE_COLOR, full_cell_rect)

        goal = Surface((CELL_SIZE, CELL_SIZE))
        draw.rect(goal, GOAL_COLOR, full_cell_rect)

        agent_rect = Rect(0, 0, AGENT_SIZE, AGENT_SIZE)
        agent = Surface((AGENT_SIZE, AGENT_SIZE))
        draw.rect(agent, AGENT_COLOR, agent_rect)

        observer_rect = Rect(0, 0, OBSERVER_SIZE, OBSERVER_SIZE)
        observer = Surface((OBSERVER_SIZE, OBSERVER_SIZE))
        draw.rect(observer, OBSERVER_COLOR, observer_rect)

        self._obstacle = obstacle
        self._goal = goal
        self._agent = agent
        self._observer = observer

    def _read_frame(self):
        """Reads a frame from the file. Returns dict of rectangles to be rendered
    Detects uneven line-lengths and raises exception"""
        self._print('reading frame')
        line = self._source_file.readline()

        while line == '\n':
            line = self._source_file.readline()

        if line == '':
            return {'eof': True}

        obstacles = []  # holds all obstacle pts
        goals = []  # holds all goal pts
        agent = None
        observer = None

        agent_offset = (CELL_SIZE - AGENT_SIZE) / 2
        observer_offset = (CELL_SIZE - OBSERVER_SIZE) / 2

        width = -1

        rows = 0
        while line != '' and line != '\n':
            column = 0
            for char in line:
                if char == '\n':
                    continue

                left, top = (CELL_SIZE * column, CELL_SIZE * rows)
                agent_left, agent_top = (
                    left + agent_offset,
                    top + agent_offset,
                )
                observer_left, observer_top = (
                    left + observer_offset,
                    top + observer_offset,
                )

                if char == '#':
                    obstacles.append((left, top))
                elif char == '*':
                    goals.append((left, top))
                elif char == '@':
                    agent = (agent_left, agent_top)
                elif char == 'O' or char == 'o':
                    observer = (observer_left, observer_top)

                column += 1

            if width < 0:
                width = column
            elif width != column:
                self._print(width, column, rows)
                raise Exception('Uneven frame')

            rows += 1
            line = self._source_file.readline()

        # if observer is obscured by agent, grab observer's last known location
        observer_obscured = False
        if observer is None and self._last_frame is not None and self._last_frame[
                'observer'] is not None:
            observer_obscured = True
            if self._last_frame['observer_obscured']:
                observer = self._last_frame['observer']
            else:
                observer = (agent[0] - agent_offset + observer_offset,
                            agent[1] - agent_offset + observer_offset)

        return {
            'eof': False,
            'obstacles': obstacles,
            'goals': goals,
            'agent': agent,
            'observer': observer,
            'observer_obscured': observer_obscured,
            'frame_size': (CELL_SIZE * (width), CELL_SIZE * (rows))
        }

    def _get_screen_size(self, frame_size):
        x, y = frame_size
        padding = 2 * SCREEN_PADDING

        if frame_size[0] < MIN_SCREEN_SIZE[0] - padding:
            x = MIN_SCREEN_SIZE[0]
        else:
            x += padding

        if frame_size[1] < MIN_SCREEN_SIZE[1] - padding:
            y = MIN_SCREEN_SIZE[1]
        else:
            y += padding

        return (x, y)

    def _get_continue_signal(self):
        self._print('Getting continue signal')
        while True:
            evt = event.wait()

            if evt.type == pygame.QUIT:
                return False

            if evt.type == pygame.KEYUP:
                if evt.key == pygame.K_RETURN or evt.key == pygame.K_KP_ENTER:
                    return True

    def _render_frame(self, frame_info):
        """Renders frame onto grid surface"""
        self._print('rendering frame onto grid surface')
        self._grid_surface.fill(WHITE)  # erase all previous

        blit_info = [(self._obstacle, obstacle_loc)
                     for obstacle_loc in frame_info['obstacles']]

        blit_info += [(self._goal, goal_loc) for goal_loc in self._goals]

        if frame_info['observer'] is not None:
            blit_info.append((self._observer, frame_info['observer']))

        if frame_info['agent'] is not None:
            blit_info.append((self._agent, frame_info['agent']))

        self._grid_surface.blits(blit_info)

    def _show_grid(self):
        self._print('updating to show currend grid surface')

        screen = display.get_surface()
        iteration_msg = self._small_msg_font.render(
            f'Iteration {self._iteration}', True, WHITE)

        screen.fill(BLACK)  # wipe everything
        screen.blits([(self._grid_surface, GRID_LOC),
                      (iteration_msg, self._iteration_msg_location)])

        display.update()
        self._last_update_time = datetime.now()

    def _render_finished_msg(self):
        screen = display.get_surface()
        finish_msg = self._title_font.render('Playback finished', True, BLUE)

        screen.blit(finish_msg, (SCREEN_PADDING * 2, SCREEN_PADDING * 2))
        display.update()
예제 #10
0
    def render_scene(self, surface: Surface, w_map: world_map.World_Map,
                     sprites: list):
        """
        renders the world using raycasting
        :param surface:
        :param world:
        :param sprites:
        :param FLOORCAST:
        :return: None
        """

        to_blit = []
        hit_direction = Camera.NORTH_SOUTH
        self.sprites_in_view = []
        self.colliding_sprites = []
        check_position = np.ndarray((2, ), np.float32)

        step_direction = np.ndarray((2, ), np.int32)

        zbuffer = np.ndarray((surface.get_width(), ), np.float32)

        draw.rect(surface, (20, 20, 20),
                  (0, 0, surface.get_width(), surface.get_height() // 2))
        draw.rect(surface, (40, 40, 40),
                  (0, surface.get_height() // 2, surface.get_width(),
                   surface.get_height() // 2))

        for screen_x in range(surface.get_width()):
            map_pos = self.pos.astype(np.int32)

            # screen_x is the column of pixels on the screen whose rendering info is being checked

            direction_variation = 2 * (
                screen_x / surface.get_width()
            ) - 1  # a scalar that represents the amount of deviation a raycasted vector will have from the facing vector

            # both x and y can be calculated in one line because of numpy magic :D
            ray_direction = self.facing_vector + self.camera_plane * direction_variation  # the facing vector + the direction variation scaled by the camera plane

            distance_between_gridline_x_y = np.absolute(1 / ray_direction)

            hit = False

            #setup initial ray cast

            if ray_direction[0] < 0:  #casting leftwards
                step_direction[0] = -1
                check_position[0] = (
                    self.pos[0] - map_pos[0]
                ) * distance_between_gridline_x_y[
                    0]  # distance from a point within the square outwards to the left side of the square
            else:  #casting rightwards
                step_direction[0] = 1
                check_position[0] = (map_pos[0] + 1 - self.pos[0]
                                     ) * distance_between_gridline_x_y[0]

            if ray_direction[1] < 0:
                step_direction[1] = -1
                check_position[1] = (self.pos[1] - map_pos[1]
                                     ) * distance_between_gridline_x_y[1]
            else:
                step_direction[1] = 1
                check_position[1] = (map_pos[1] + 1 - self.pos[1]
                                     ) * distance_between_gridline_x_y[1]
            #begin casting ray
            while not hit:
                if check_position[0] < check_position[1]:
                    check_position[0] += distance_between_gridline_x_y[0]
                    map_pos[0] += step_direction[0]
                    hit_direction = Camera.EAST_WEST
                else:
                    check_position[1] += distance_between_gridline_x_y[1]
                    map_pos[1] += step_direction[1]
                    hit_direction = Camera.NORTH_SOUTH
                if w_map.map_data[map_pos[0]][map_pos[1]] != 0:
                    hit = True

            if hit_direction == Camera.EAST_WEST:
                distance = (map_pos[0] - self.pos[0] +
                            (1 - step_direction[0]) / 2) / ray_direction[0]
            else:
                distance = (map_pos[1] - self.pos[1] +
                            (1 - step_direction[1]) / 2) / ray_direction[1]

            #distance to surface has been found, now to calculate the height of the wall onscreen

            if distance == 0:
                distance = 1

            lineHeight = surface.get_height() // distance

            hit_data = w_map.map_data[map_pos[0]][map_pos[1]]

            start_y = int(surface.get_height() // 2 - lineHeight // 2)

            end_y = int(surface.get_height() // 2 + lineHeight // 2)

            if hit_direction == Camera.EAST_WEST:
                pixel_pos = self.pos[1] + distance * ray_direction[1]
            else:
                pixel_pos = self.pos[0] + distance * ray_direction[0]
            pixel_pos = (pixel_pos - math.floor(pixel_pos))
            blitPixels = w_map.textures[hit_data].subsurface(
                (int(pixel_pos * w_map.textures[hit_data].get_width()), 0, 1,
                 w_map.textures[hit_data].get_height())).copy()

            if hit_direction == Camera.EAST_WEST:
                darkenSurf = Surface((1, blitPixels.get_height()))
                darkenSurf.set_alpha(128)
                blitPixels.blit(darkenSurf, (0, 0))
            darkenSurf = Surface((1, blitPixels.get_height()))
            darkenSurf.set_alpha(min(20 * distance, 255))
            blitPixels.blit(darkenSurf, (0, 0))

            scaled_pixels = transform.scale(blitPixels,
                                            (1, min(end_y - start_y, 50000)))

            to_blit.append((scaled_pixels, (screen_x, start_y)))

            # fill in z buffer

            zbuffer[screen_x] = distance

        # sprite casting
        sprites = [s for s in sprites if s != self]

        sprite_draw_order = [(0, 0) for i in range(len(sprites))]

        for i, sprite in enumerate(sprites):
            sprite_draw_order[i] = (((self.pos[0] - sprite.pos[0])**2 +
                                     (self.pos[1] - sprite.pos[1])**2), i)

        sprite_draw_order.sort(reverse=True)

        for i, v in enumerate(sprite_draw_order):
            seen_sprite = False
            draw_sprite = sprites[v[1]].get_sprite(self.facing_vector)
            sprite_pos_rel_to_camera = sprites[v[1]].pos - self.pos
            if (sprite_pos_rel_to_camera[0] == 0
                    and sprite_pos_rel_to_camera[1] == 0):
                sprite_pos_rel_to_camera[0] = 0.01
                sprite_pos_rel_to_camera[1] = 0.01

            if math.hypot(sprite_pos_rel_to_camera[0],
                          sprite_pos_rel_to_camera[1]) < 0.4:
                self.colliding_sprites.append(sprites[v[1]])

            invDet = 1 / (self.camera_plane[0] * self.facing_vector[1] -
                          self.facing_vector[0] * self.camera_plane[1])

            transformX = invDet * (
                self.facing_vector[1] * sprite_pos_rel_to_camera[0] -
                self.facing_vector[0] * sprite_pos_rel_to_camera[1])
            transformY = invDet * (
                -self.camera_plane[1] * sprite_pos_rel_to_camera[0] +
                self.camera_plane[0] * sprite_pos_rel_to_camera[1])
            spriteScreenPos = int(
                (surface.get_width() / 2) * (1 + transformX / transformY))

            sprite_height = abs(int(surface.get_height() / transformY))

            sprite_width = abs(int(surface.get_height() / transformY))

            start_x = spriteScreenPos - sprite_width // 2
            if start_x < 0:
                start_x = 0

            end_x = spriteScreenPos + sprite_width // 2
            if end_x > surface.get_width():
                end_x = surface.get_width() - 1

            for draw_stripe_x in range(start_x, end_x):
                textureX = int(256 * (draw_stripe_x -
                                      (-sprite_width / 2 + spriteScreenPos)) *
                               draw_sprite.get_width() / sprite_width) / 256
                if 0 < transformY and 0 < draw_stripe_x:
                    if transformY < zbuffer[
                            draw_stripe_x] and draw_stripe_x < surface.get_width(
                            ):

                        spriteSlice = transform.scale(
                            draw_sprite.subsurface(
                                (textureX, 0, 1,
                                 draw_sprite.get_height())).copy(),
                            (1, min(sprite_height, 50000)))

                        shaderSurf = Surface(
                            (1, min(spriteSlice.get_height(), 400)), SRCALPHA)
                        shade_val = min(
                            22 * math.hypot(sprite_pos_rel_to_camera[0],
                                            sprite_pos_rel_to_camera[1]), 255)

                        shaderSurf.fill([
                            255 - shade_val, 255 - shade_val, 255 - shade_val
                        ])

                        spriteSlice.blit(
                            shaderSurf, (0, 0), (0, 0) + shaderSurf.get_size(),
                            BLEND_MULT
                        )  # blend mult multiplies each rgb value by the blitter's rgb/255 value

                        to_blit.append(
                            (spriteSlice,
                             (draw_stripe_x, surface.get_height() // 2 -
                              spriteSlice.get_height() // 2)))

                        if draw_stripe_x == int(
                                surface.get_width() // 2
                        ):  # if the stripe goes through the user's crosshairs
                            seen_sprite = True
            if seen_sprite:
                self.sprites_in_view.append(sprites[v[1]])

        surface.blits(to_blit)
        return surface
예제 #11
0
class TileMenuFrame(Sprite):
    def __init__(self, sx, sy, w, h, camera, bgnd=None, brdr=None):
        Sprite.__init__(self)
        self.sx = sx
        self.sy = sy
        self.w = w
        self.h = h
        self.tw = int(w/TileService.size)
        self.th = int(h/TileService.size)
        if(bgnd is None):
            bgnd = TileService.getTile((0,0))
        if(brdr is None):
            brdr = TileService.getTile((11,13))
        self.background = bgnd
        self.border = brdr
        self.image = Surface((self.w, self.h))
        self.rect = (
            self.sx,
            self.sy,
            self.w,
            self.h
        )
        self.fill(self.background)
        self.addBorder(self.border)
        camera.add(self)

    def fill(self, tile):
        blits = []
        for y in range(0, self.th):
            for x in range(0, self.tw):
                blits.append((tile, (x*TileService.size, y*TileService.size)))
        self.image.blits(blit_sequence=blits)

    def addBorder(self, brdr):
        self.border = brdr
        if(self.border is not None):
            blits = []
            for y in range(0,self.th):
                for x in range(0,self.tw):
                    if(y == 0 or x == 0 or y == self.th-1 or x == self.tw-1):
                        blits.append((self.getBorderTile(x,y),(x*TileService.size,y*TileService.size)))
            self.image.blits(blit_sequence=blits)

    def getBorderTile(self, x, y):
        if(isinstance(self.border, dict) or isinstance(self.border, TileBorder)):
            if(y == 0 and x == 0):
                return self.border['tl'].copy()
            elif(y == 0 and x == self.tw-1):
                return self.border['tr'].copy()
            elif(y == 0 and x != self.tw-1):
                return self.border['t'].copy()
            elif(y == self.th-1 and x == 0):
                return self.border['bl'].copy()
            elif(y == self.th-1 and x == self.tw-1):
                return self.border['br'].copy()
            elif(y == self.th-1 and x != self.tw-1):
                return self.border['b'].copy()
            elif(y != self.th-1 and x == 0):
                return self.border['l'].copy()
            elif(y != self.th-1 and x == self.tw-1):
                return self.border['r'].copy()
            else:
                return TileService.getTile((0,0))
        else:
            return self.border