import pygame from pygame import gfxdraw import os from PIL import Image from PIL import ImageDraw from gui_util import draw_dashed_line_delay ROAD_HEIGHT = 250.0 COLOR = {"white": pygame.Color(255, 255, 255), "opaque_white": pygame.Color(255, 255, 255, 80), "text": pygame.Color(172, 199, 252), "dark_text": pygame.Color(57, 84, 137), "selection": [pygame.Color(172, 199, 252), pygame.Color(100, 149, 252)], "sky": pygame.Color(10, 10, 10), "gutter": pygame.Color(100, 100, 100), "red": pygame.Color(204, 0, 0), "bonus_a": pygame.Color(255, 78, 0), "bonus_b": pygame.Color(255, 178, 0), "green": pygame.Color(32, 76, 1), "black": pygame.Color(0, 0, 0), "tunnel": pygame.Color(38, 15, 8), "brown": pygame.Color(124, 69, 1)} class AdvancedRoad: def __init__(self, surface, origin_x, origin_y, width, height, lane=6): self.surface = surface self.sky_x = 0 self.sky_y = 0 self.sky_height = 800 - ROAD_HEIGHT self.sky_width = width self.origin_x = origin_x # Road origin_x self.origin_y = origin_y # Road origin_y self.width = width # Road width self.height = height # Road height self.lane = lane self.sky_image = pygame.image.load(os.path.join('./advanced_view/images/sky_1010x550.png')) self.hill_image = pygame.image.load(os.path.join('./advanced_view/images/hill.png')) self.field_left_image = pygame.image.load(os.path.join('./advanced_view/images/field_left.png')) self.field_right_image = pygame.image.load(os.path.join('./advanced_view/images/field_right.png')) self.field_side_left_image = pygame.image.load(os.path.join('./advanced_view/images/field_side_left.png')) self.field_side_right_image = pygame.image.load(os.path.join('./advanced_view/images/field_side_right.png')) self.field_image = Image.open(os.path.join('./advanced_view/images/field.png')).convert("RGBA") # self.dirt_image = pygame.image.load(os.path.join('./advanced_view/images/dirt.png')) self.dirt_image = Image.open(os.path.join('./advanced_view/images/dirt.png')).convert("RGBA") self.subject_car_middle_image = pygame.image.load(os.path.join('./advanced_view/images/chev_rear.png')) self.subject_car_left_image = pygame.image.load(os.path.join('./advanced_view/images/chev_left.png')) self.subject_car_right_image = pygame.image.load(os.path.join('./advanced_view/images/chev_right.png')) self.object_car_middle_image = pygame.image.load(os.path.join('./advanced_view/images/civic_rear.png')) self.object_car_left_image = pygame.image.load(os.path.join('./advanced_view/images/civic_left.png')) self.object_car_right_image = pygame.image.load(os.path.join('./advanced_view/images/civic_right.png')) self.road_view = None def draw(self, frame, subject_car): lane = subject_car.lane while True: self.draw_sky(frame) self.draw_road_side(frame, self.lane) self.draw_road(frame, lane=self.lane) self.draw_cars(subject_car) self.draw_subject_car(self.lane - lane) if self.lane != lane: self.lane += 0.25 if lane > self.lane else - 0.25 if abs(self.lane - lane) < 0.1: break pygame.event.poll() pygame.display.flip() self.lane = lane def draw_sky(self, frame): view = pygame.Surface((self.sky_width, self.sky_height)) # Resize sky if frame % 40 == 0: self.sky_image = pygame.transform.scale(self.sky_image, (self.sky_image.get_size()[0]+2, self.sky_image.get_size()[1]+1)) self.sky_image.blit(self.sky_image, ((-1, -2), (self.sky_width, self.sky_height))) view.blit(self.sky_image, ((0, 0), (self.sky_width, self.sky_height))) view.blit(self.hill_image, ((0, self.sky_height - 49), (self.sky_width, 49))) self.surface.blit(view, ((self.sky_x, self.sky_y), (self.sky_width, self.sky_height))) def draw_cars(self, subject_car): view = pygame.Surface((1010, ROAD_HEIGHT), pygame.SRCALPHA, 32) view = view.convert_alpha() camera_lane = subject_car.lane cars = subject_car.get_subjective_vision() for car in cars: lane = car[0] y = car[1] relative_y = y - 42 if relative_y < 0: continue image = self.object_car_middle_image ratio = 231.0 / 328.0 if lane != camera_lane: if lane > camera_lane: image = self.object_car_right_image else: image = self.object_car_left_image pt_top_left = (lane - 1) * 100.0 / 7 + 455 pt_top_right = lane * 100.0 / 7 + 455 pt_bottom_left = -337.0 * camera_lane + 673.33 + (lane - 1) * 337.0 pt_bottom_right = -337.0 * camera_lane + 673.33 + lane * 337.0 target_y = ROAD_HEIGHT * relative_y / 28.0 target_bottom_left_x = pt_top_left + target_y / ROAD_HEIGHT * (pt_bottom_left - pt_top_left) target_bottom_right_x = pt_top_right + target_y / ROAD_HEIGHT * (pt_bottom_right - pt_top_right) image_width = int(target_bottom_right_x - target_bottom_left_x - 10) image_width = image_width if image_width > 0 else 0 image_height = int(image_width * ratio) target_top_left_x = int(target_bottom_left_x + 5) target_top_left_y = int(target_y - image_height) a = pygame.transform.scale(image, (image_width, image_height)) view.blit(a, (target_top_left_x, target_top_left_y)) self.surface.blit(view, ((self.origin_x, self.origin_y), (self.width, self.height))) def draw_road_side(self, frame, lane): polygon_left = [ (-337.0 * lane + 673.33 - 200, ROAD_HEIGHT), (455 - 20, 0), (0, 0), (0, ROAD_HEIGHT)] polygon_right = [ (1010, ROAD_HEIGHT), (1010, 0), (555 + 20, 0), (-336.67 * lane + 3032 + 200, ROAD_HEIGHT)] maskIm = self.dirt_image.crop((0, 500 - (frame % 20) * 25, self.width, ROAD_HEIGHT + 500 - (frame % 20) * 25)) pdraw = ImageDraw.Draw(maskIm) pdraw.polygon(polygon_left, fill=(255, 255, 255, 0), outline=(255, 255, 255, 0)) pdraw.polygon(polygon_right, fill=(255, 255, 255, 0), outline=(255, 255, 255, 0)) side = self.field_image.crop((0, 500 - (frame % 20) * 25, self.width, ROAD_HEIGHT + 500 - (frame % 20) * 25)) side.paste(maskIm, (0, 0), mask=maskIm) side_pygame = pygame.image.fromstring(side.tobytes(), side.size, side.mode) self.surface.blit(side_pygame, ((self.origin_x, self.origin_y), (self.width, ROAD_HEIGHT))) def blit_mask(source, dest, destpos, mask, maskrect): """ Blit an source image to the dest surface, at destpos, with a mask, using only the maskrect part of the mask. """ tmp = source.copy() tmp.blit(mask, maskrect.topleft, maskrect, special_flags=pygame.BLEND_RGBA_MULT) dest.blit(tmp, destpos, dest.get_rect().clip(maskrect)) def draw_road(self, frame, lane=1): self.road_view = pygame.Surface((1010, ROAD_HEIGHT), pygame.SRCALPHA, 32) self.road_view = self.road_view.convert_alpha() pygame.draw.polygon(self.road_view, COLOR['black'], [ (-337.0 * lane + 673.33, ROAD_HEIGHT), (455, 0), (555, 0), (-336.67 * lane + 3032, ROAD_HEIGHT) ]) left = -337.0 * lane + 673.33 for i in range(8): if i == 0 or i == 7: gfxdraw.filled_polygon(self.road_view, ( (int(int(i * 100.0 / 7 + 455)), 0), (int(int(i * 100.0 / 7 + 455)) + 7, 0), (int(left) + 7, int(ROAD_HEIGHT)), (int(left), int(ROAD_HEIGHT)) ), COLOR['white']) else: draw_dashed_line_delay(self.road_view, COLOR['white'], (i * 100.0 / 7 + 455, 0), (left, ROAD_HEIGHT), width=5, dash_length=40, delay=frame % 3) left += 337.0 self.surface.blit(self.road_view, ((self.origin_x, self.origin_y), (self.width, self.height))) def draw_subject_car(self, direction): image = self.subject_car_middle_image if direction > 0: image = self.subject_car_left_image elif direction < 0: image = self.subject_car_right_image self.surface.blit(image, (self.origin_x + 345, self.origin_y + 70))