def test_vector_add_int(self): vec1 = Vector(10, 0) res = vec1 + 10 expected = Vector(20, 10) notExpected = Vector(20, 10, 10) self.assertEqual(expected, res) self.assertNotEqual(notExpected, res)
def add_button(self, surface: Surface, row, col): coord = Vector(self.min_width + row * (BUTTON_SIZE + DEFAULT_MARGIN), self.min_height + col * (BUTTON_SIZE + DEFAULT_MARGIN)) size = Vector(BUTTON_SIZE, BUTTON_SIZE) floor = compute_floor(row, col) button = Button(coord, size, floor) self.buttons.append(button) return button.display(surface)
def __init__(self, sprite_sheet_id, idx=0): super().__init__() self.sprite_sheet: SpriteSheet = ImagesCache( ).sprites_sheets[sprite_sheet_id] self.elapsed_time = 0 self.pos = Vector() self.scale = Vector() self.sprites = self.sprite_sheet.all_sprites() self.idx = idx
def add_image(surface: Surface, image: Surface, pos: Vector = Vector(0, 0), scale: Vector = None, angle=0): if angle != 0: rotated_img = rot_center(image, angle) else: rotated_img = image if not scale is None: rescaled_img = pygame.transform.scale(rotated_img, scale.to_pos()) else: rescaled_img = image return functools.partial(surface.blit, rescaled_img, pos.to_pos())
def display(self, game_display, dt): self.image = ImagesCache().images[self.client_name] move = Vector(0, 500) if self.accumulated_time < IN_OUT_TIME_SECOND: self.accumulated_time += dt / 1000 else: self.finished = True per = self.accumulated_time / IN_OUT_TIME_SECOND if self.is_in: move = move.multiply(1 - per) else: move = move.multiply(per) height = self.image.get_rect().size[1] pos = POS_CHARACTER - Vector(0, height) + move return functools.partial(game_display.blit, self.image, pos.to_pos())
def __init__(self, floor): if floor is None: self.floor = -1 else: self.floor = floor self.size = Vector(dimensions.WINDOW_WIDTH, dimensions.WINDOW_HEIGHT) self.persistent_name = 'background'
def on_click(game_display: Surface, event: EventType, displayables): click_coordinate = event.dict['pos'] pos = Vector(*click_coordinate) for button in ButtonBuilder().buttons: if button.is_inside(pos): return FloorSelected(button.floor) return UserKeyAction()
def display_dialog(surface: Surface, name: str, dialog: str): WIDTH = 455 HEIGHT = 205 BORDER = 5 IN_WIDTH = WIDTH - BORDER IN_HEIGHT = HEIGHT - BORDER canevas = Surface((WIDTH, HEIGHT)) canevas.fill(color.TEXT_BACKGROUND_COLOR) pos = Vector(dimensions.WINDOW_WIDTH - (30 + IN_WIDTH), dimensions.WINDOW_HEIGHT - (30 + IN_HEIGHT)) sizes = Vector(IN_WIDTH, IN_HEIGHT) rect = pygame.Rect(Vector().to_pos(), sizes.to_pos()) draw.rect(canevas, color.WHITE, rect, 5) font_name = ImagesCache().fonts["dialog"].render("{}: ".format(name), True, color.TEXT_NAME_COLOR) canevas.blit(font_name, (5, 4)) height = 30 for line in break_dialog_lines(dialog): font_text = ImagesCache().fonts["dialog"].render( line, True, color.TEXT_FOREGROUND_COLOR) canevas.blit(font_text, (10, height)) height += 20 return functools.partial(surface.blit, canevas, pos.to_pos())
def construct_background(self, game_display): background_sprite_sheet: SpriteSheet = self.image_cache.sprites_sheets['background'] background_sprite = background_sprite_sheet.get_element(0, 0) self.persistent_display['background'] = \ drawer.add_image(game_display, background_sprite, Vector(), Vector(dimensions.WINDOW_WIDTH, dimensions.WINDOW_HEIGHT), 0) self.persistent_display['floor-indicator'] = \ drawer.add_image(game_display, self.image_cache.images['floor-indicator'], DEFAULT_FLOOR_INDICATOR_POS, DEFAULT_FLOOR_INDICATOR_SCALE, 89) self.persistent_display['client'] = NoClientAction().display(game_display, 0) self.persistent_display['elevator-gate'] = ElevatorGateOpenAction().display(game_display, 0)
def display(self, game_display, dt): def nop(): pass if self.client_name is None: return nop image = ImagesCache().images[self.client_name] height = image.get_rect().size[1] return drawer.add_image(game_display, image, POS_CHARACTER - Vector(0, height))
def main(self): game_display: Surface = display.set_mode((self.display_width, self.display_height)) display.set_caption('Natural 20: Challenge Pixel 2017') clock: Clock = pygame.time.Clock() self.construct_background(game_display) self.init_keypad(game_display) crashed = False _ = BackgroundMusicTrack() while not crashed: game_display.fill(color.BLACK) self.compute_delta_t() for displayable in self.persistent_display.values(): displayable() for displayable in self.temporary_display: displayable() self.temporary_display.clear() str_tips = "{:>6.2f}$".format(Blackboard().tips) self.temporary_display.append(drawer.add_text(game_display, str_tips, Vector(90, 380), color.MONEY_COLOR)) for event in pygame.event.get(): if event.type == pygame.QUIT: crashed = True else: self.actions.append(handler.handle(game_display, event, self.persistent_display)) self.actions = [action for action in self.actions if action] domain_actions = self.state_executor.exec(self.delta_t, self.actions) self.actions.clear() for domain_action in domain_actions: if domain_action.persistent_name: self.persistent_display[domain_action.persistent_name] =\ domain_action.display(game_display, self.delta_t) else: self.temporary_display.append(domain_action.display(game_display, self.delta_t)) # TEST pygame.display.update() clock.tick(FPS)
def init_cache(self): background_idx, background_path = images.BACKGROUND_IMAGE self.image_cache.add_sprites_sheets(background_idx, background_path, Vector(1024, 1024)) self.image_cache.add_image(*images.FLOOR_INDICATOR) self.image_cache.add_image(*images.ELEVATOR_GATE) self.image_cache.add_font("dialog", "resource/font/OldNewspaperTypes.ttf", DIALOG_POLICE_SIZE) self.image_cache.add_font("tips", "resource/font/OldStandard-Regular.ttf", 20) with open('resource/json/clients.json') as json_file: json_raw = json.load(json_file) for client in json_raw["clients"]: ImagesCache().add_image(client["name"], client["ressource"]) for i in range(10): idx, path = images.BUTTON_PATTERN idx = idx.format(i) path = path.format(i) self.image_cache.add_sprites_sheets(idx, path, button.BUTTON_SPRITE_SIZE)
def __init__(self): super().__init__() self.coordinates = DEFAULT_POSITION self.size = Vector(OPEN_WIDTH, DEFAULT_HEIGHT) self.accumulated_time = 0 self.persistent_name = 'elevator-gate'
def __init__(self, sprite_sheet_path: str, element_dimensions: Vector): self.image = pygame.image.load(sprite_sheet_path) self.image_size = Vector(*self.image.get_rect().size) self.element_dimensions = element_dimensions
def add_rectangle(surface: Surface, coord: Vector, size: Vector, rect_color: Tuple[int, int, int]): rect = pygame.Rect(coord.to_pos(), size.to_pos()) return functools.partial(draw.rect, surface, rect_color, rect, 0)
def add_text(surface: Surface, text: str, pos: Vector, text_color=color.TEXT_FOREGROUND_COLOR): font_text = ImagesCache().fonts["tips"].render(text, True, text_color) return functools.partial(surface.blit, font_text, pos.to_pos())
import pygame from display import drawer from display.action.interface import IDomainAction from display.cache import ImagesCache from util.animation import easing from util.geometry import Vector DEFAULT_FLOOR_INDICATOR_IMAGE_PATH = 'resource/img/level_counter.png' DEFAULT_FLOOR_INDICATOR_POS = Vector(135-108, 105-106) DEFAULT_FLOOR_INDICATOR_SCALE = Vector(210, 210) DEFAULT_TIME_TO_CLIMB_A_FLOOR = 4 floor_to_angle = {0: 89, 1: 75, 2: 60, 3: 35, 4: 10, 5: -10, 6: -35, 7: -60, 8: -75, 9: -89} class FloorIndicatorAction(IDomainAction): def __init__(self, actual_floor, target_floor): super().__init__() self.angle = floor_to_angle[actual_floor] self.initial_angle = floor_to_angle[actual_floor]
from display import drawer from display.action.interface import IDomainAction from display.cache import ImagesCache from util.animation import easing from util.geometry import Vector DEFAULT_POSITION = Vector(275, 0) OPEN_WIDTH = 125 CLOSED_WIDTH = 520 DEFAULT_HEIGHT = 600 DEFAULT_TIME_DOOR = 2 class ElevatorGateOpenAction(IDomainAction): def __init__(self): super().__init__() self.coordinates = DEFAULT_POSITION self.size = Vector(CLOSED_WIDTH, DEFAULT_HEIGHT) self.accumulated_time = 0 self.persistent_name = 'elevator-gate' def display(self, game_display, dt): self.accumulated_time += (dt / 1000) image = ImagesCache().images['elevator-gate'] self.start_sound_effect("resource/sounds/Porte-ouvre-ferme-2s.wav") if self.accumulated_time < DEFAULT_TIME_DOOR: delta_x = OPEN_WIDTH - CLOSED_WIDTH width = CLOSED_WIDTH + easing(self.accumulated_time, 0, delta_x, DEFAULT_TIME_DOOR) self.size.x = int(width)
def display(self, game_display, dt): self.finished = True sprite_sheet: SpriteSheet = ImagesCache().sprites_sheets['background'] sprite = sprite_sheet.get_element(0, self.floor + 1) return drawer.add_image(game_display, sprite, Vector(), self.size)
from display import drawer from display.action.interface import IDomainAction from display.cache import ImagesCache from util.geometry import Vector POS_CHARACTER = Vector(418, 770) class ClientAction(IDomainAction): def __init__(self, client_name: str): super().__init__() self.client_name = client_name self.persistent_name = 'client' def display(self, game_display, dt): def nop(): pass if self.client_name is None: return nop image = ImagesCache().images[self.client_name] height = image.get_rect().size[1] return drawer.add_image(game_display, image, POS_CHARACTER - Vector(0, height)) class NoClientAction(ClientAction): def __init__(self): super().__init__(None)
def test_vector_add_vector(self): vec1 = Vector(10, 10, 0) vec2 = Vector(10, 20, 0) res = vec1 + vec2 expected = Vector(20, 30, 0) self.assertEqual(expected, res)
def test_given_button_when_pos_is_inside_return_true(self): button = Button(Vector(100, 100), Vector(25, 25), None) pos = Vector(105, 105) self.assertTrue(button.is_inside(pos))
import functools import pygame from pygame import draw from pygame.surface import Surface from display import color, drawer from display.cache import ImagesCache from display.spritesheet import SpriteSheet from util.geometry import Vector from util.singleton import Singleton from domain import images BUTTON_SIZE = 26 BUTTON_SPRITE_SIZE = Vector(107, 107) DEFAULT_MIN_WIDTH = 107 DEFAULT_MIN_HEIGHT = 175 DEFAULT_MARGIN = 2 NUMBER_OF_BUTTONS_ROWS = 5 NUMBER_OF_BUTTONS_COLS = 2 class Button: def __init__(self, coordinates: Vector, size: Vector, floor: int): idx, _ = images.BUTTON_PATTERN self.idx = idx.format(floor) self.coordinates = coordinates self.size = size self.floor = floor def display(self, surface: Surface):