def __init__(self, position, value, values, width, height, puck_radius, text, text_colour, text_font, text_box_width, text_box_height, slider_type="default"): self.__value = value self.values = values self.timer = 0 position = position + Vector(0, text_box_height / 2) Rectangle.__init__(self, width, height, position) self.puck = Circle(puck_radius, position) self.states = {} for state in ["active", "hover", "normal"]: self.puck.load_avatar( r"GUI/Slider/{0}/{1}.png".format(slider_type, state)) self.puck.scale_avatar( self.puck.radius * 2, self.puck.radius * 2) self.states[state] = self.puck.image_master self.sound_effect = SoundEffect(r"slider_{0}.wav".format(slider_type)) self.state = "normal" self.text_box = TextBox( text_box_width, text_box_height, position + Vector(0, -max(self.puck.radius, height / 2) - text_box_height / 2), text, text_colour, text_font) self.left_fill = (253, 238, 0) self.right_fill = (0, 0, 0) self.slider_type = slider_type self.sync_puck()
def __init__(self, colour, width, height, x, y, tag=TAG_GROUND): self.width, self.height = width, height self.x, self.y = x, y self.tag = tag self.colour = colour self.rect = Rectangle(width, height, Vector(x + width / 2, y + height / 2))
def update(self, timer, world, events): self.functionality(events, world) way_point = Vector(self.aim) - Vector(self.rect.center) bearing = way_point.normalize() self.image = pygame.transform.rotate(self.image_master, way_point.angle_to(Vector(1, 0))) self.rect = Rectangle.get_rect(self.image, self.rect.center) if not self.should_retract: self.hook_image = pygame.transform.rotate( self.hook_image_master, way_point.angle_to(Vector(1, 0))) self.hook_rect = Rectangle.get_rect(self.hook_image, self.hook_rect.center) self.hitmask = get_hitmask(self.hook_rect, self.hook_image, 0) self.x = self.rect.x self.y = self.rect.y if self.shooter: self.shoot(timer) self.should_retract = True self.should_aim = False elif not self.should_retract: self.hook_rect = Rectangle.get_rect( self.hook_image, (self.rect.center[0] + bearing.x * self.displacement, self.rect.center[1] + bearing.y * self.displacement)) if self.should_retract and not self.shooter: self.retract(timer) if self.should_release: self.release(timer)
def setup_menu_camera(self): # this is the menu bar self.menu = Rectangle(WIDTH // 4, HEIGHT, (WIDTH - WIDTH // 4 + (WIDTH // 4) // 2, HEIGHT // 2)) self.camera = Camera(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1], WIDTH - WIDTH // 4, HEIGHT)
def __init__(self, width, height, position, text, text_colour, text_font, background=None): Rectangle.__init__(self, width, height, position) self.text = text self.text_colour = text_colour self.text_font = text_font self.background = background self.create_text_avatar()
class Block(): def __init__(self, colour, width, height, x, y, tag=TAG_GROUND): self.width, self.height = width, height self.x, self.y = x, y self.tag = tag self.colour = colour self.rect = Rectangle(width, height, Vector(x + width / 2, y + height / 2)) def draw(self, screen, camera=0): self.rect.draw(screen, self.colour, camera)
def __init__(self, width, height, position, title, title_colour, title_font, title_box_width, title_box_height, menu_type="default"): Rectangle.__init__(self, width, height, position) self.load_avatar(r"GUI/Menu/{0}.jpg".format(menu_type)) self.elements = [TextBox( title_box_width, title_box_height, Vector(width / 2, title_box_height / 2 + 10), title, title_colour, title_font)] self.frame = ((0, 0, 0), 10) self.menu_type = menu_type
def test_collide(self): class Test: def __init__(self, rect, hitmask): self.rect = rect self.hitmask = hitmask rect2 = Rectangle(2, 2, (1, 2)) rect1 = Rectangle(2, 2, (1, 1)) sprite_a = Test(rect1, [[True, True], [True, True]]) sprite_b = Test(rect2, [[True, True], [True, True]]) rect2 = Rectangle(2, 2, (1, 15)) self.assertEqual(collide(sprite_b, sprite_a), True) sprite_b = Test(rect2, [[True, True], [True, True]]) self.assertEqual(collide(sprite_b, sprite_a), False)
def __init__(self, position, width, height, text, text_colour, text_font, button_type="default"): Rectangle.__init__(self, width, height, position) self.states = {} for state in ["active", "hover", "normal"]: self.load_avatar( r"GUI/Button/{0}/{1}.png".format(button_type, state)) self.scale_avatar(self.width, self.height) self.states[state] = self.image_master self.state = "normal" self.clicked = False self.sound_effect = SoundEffect(r"button_{0}.wav".format(button_type)) self.text_box = TextBox(width, height, position, text, text_colour, text_font) self.button_type = button_type
def __init__(self, x, y, length): """ x and y should be the coordinates of the pivot """ self.rope_height = length self.x, self.y = x, y self.rope_width = SAW_ROPE_WIDTH self.saw_image_master = image.load( "../ArtWork/Environment/{0}".format(SAW_IMAGE)).convert_alpha() self.saw_image_master = transform.scale(self.saw_image_master, SAW_DIMENSION) self.image = self.saw_image_master self.center_old = Vector(x, y + self.rope_height + 15) self.rect = Rectangle.get_rect(self.image, self.center_old) self.collision_circle = Circle(25, self.center_old) self.step = ROTATION_STEP self.rotation = 0 self.time = 0 self.last_time = 0 self.current_time = 0 self.direction = Vector((0, 0)) self.velocity = Vector((0, 0)) self.bob = Pendulum(SAW_ROPE_ANGLE, self.rope_height, (self.x, self.y)) self.is_severed = False
def recompute_angle(self): self.time += 1 # modulates gravity scaling = 2000 / (self.swing_length**2) first_d_d_theta = -sin(radians(self.theta)) * scaling mid_d_theta = self.d_theta + first_d_d_theta mid_theta = self.theta + (self.d_theta + mid_d_theta) / 2.0 mid_d_d_theta = -sin(radians(mid_theta)) * scaling mid_d_theta = self.d_theta + (first_d_d_theta + mid_d_d_theta) / 2 mid_theta = self.theta + (self.d_theta + mid_d_theta) / 2 mid_d_d_theta = -sin(radians(mid_theta)) * scaling last_d_theta = mid_d_theta + mid_d_d_theta last_theta = mid_theta + (mid_d_theta + last_d_theta) / 2.0 last_d_d_theta = -sin(radians(last_theta)) * scaling last_d_theta = mid_d_theta + (mid_d_d_theta + last_d_d_theta) / 2.0 last_theta = mid_theta + (mid_d_theta + last_d_theta) / 2.0 self.d_theta = last_d_theta self.theta = last_theta self.rect = Rectangle( 1, 1, (int(self.pivot[0] - self.swing_length * sin(radians(self.theta))), int(self.pivot[1] + self.swing_length * cos(radians(self.theta)))))
def __init__(self, width, height, window_width, window_height): self.state = Rectangle(width, height, Vector(0 + width // 2, 0 + height // 2)) self.half_width = window_width // 2 self.half_height = window_height // 2 self.window_width = window_width self.window_height = window_height
def __init__(self, position, size, message, colour, text_colour): self.rect = Rectangle(size[0], size[1], Vector(position[0] + size[0] // 2, position[1] + size[1] // 2)) self.message = message self.colour = colour self.text_colour = text_colour self.font = font.Font(None, 32) self.position = position
def __init__(self, angle, swing_length, pivot): self.theta = angle self.d_theta = 0 self.swing_length = swing_length self.pivot = pivot self.time = 0 self.rect = Rectangle( 1, 1, (int(self.pivot[0] - self.swing_length * cos(radians(self.theta))), int(self.pivot[1] + self.swing_length * sin(radians(self.theta)))))
def swing(self): self.current_time = pygame.time.get_ticks() if self.current_time - self.last_time >= 17: self.bob.recompute_angle() self.step = self.bob.d_theta self.rope = self.rope.rotate(self.step) self.rect = Rectangle.get_rect(self.image, self.bob.rect.center) self.x = self.rect.x self.y = self.rect.y self.last_time = self.current_time
class Button: def __init__(self, position, size, message, colour, text_colour): self.rect = Rectangle(size[0], size[1], Vector(position[0] + size[0] // 2, position[1] + size[1] // 2)) self.message = message self.colour = colour self.text_colour = text_colour self.font = font.Font(None, 32) self.position = position def is_pressed(self, mouse_position, events): for event in events: if event.type == MOUSEBUTTONUP: if self.rect.is_point_in_body(mouse_position): return True return False def draw(self, screen): self.rect.draw(screen, self.colour) text = self.font.render(self.message, 20, self.text_colour) screen.blit(text, self.position)
def __init__(self, position, value, width, height, text, text_colour, text_font, text_box_width, text_box_height, checkbox_type="default"): Rectangle.__init__(self, width, height, position + Vector( -text_box_width / 2, 0)) self.states = {} for state in ["checked", "unchecked", "checked_hover", "unchecked_hover"]: self.load_avatar( r"GUI/Checkbox/{0}/{1}.png".format(checkbox_type, state)) self.scale_avatar(self.width, self.height) self.states[state] = self.image_master if value: self.state = "checked" else: self.state = "unchecked" self.sound_effect = SoundEffect( r"checkbox_{0}.wav".format(checkbox_type)) self.text_box = TextBox( text_box_width, text_box_height, self.position + Vector((self.width + text_box_width) / 2, 0), text, text_colour, text_font) self.checkbox_type = checkbox_type
def __init__(self, x, y): self.image_master = \ pygame.image.load("../ArtWork/Environment/graple.png")\ .convert_alpha() self.image_master = pygame.transform.scale(self.image_master, (80, 40)) self.image = self.image_master self.hook_image_master = \ pygame.image.load("../ArtWork/Environment/hook2.png")\ .convert_alpha() self.hook_image_master = pygame.transform.scale( self.hook_image_master, (40, 40)) self.hook_image = self.hook_image_master self.displacement = (self.hook_image_master.get_width() + self.image_master.get_width()) // 2 self.hook_rect = Rectangle.get_rect(self.hook_image, (x, y)) self.rect = Rectangle.get_rect(self.image, (x, y)) self.hooker = Vector((self.hook_rect.x, self.hook_rect.y)) self.hitmask = get_hitmask(self.hook_rect, self.hook_image, 0) self.aim = (x, y + 20) self.should_aim = True self.should_retract = False self.limit = Vector(1, 0) self.angle = 0 self.rotation = 0 self.step = 0 self.should_release = False self.time = 0 self.distance_limit = 150 self.x = self.rect.x self.y = self.rect.y self.current_time = 0 self.last_time = 0 self.shooter = False self.calculate_pivot = True
def functionality(self, target): """defines how the camera will move, also makes sure it doesn't go outside level space """ left, top = target[0], target[1] left = self.half_width - left top = self.half_height - top left = min(0, left) left = max((self.window_width - self.state.width), left) top = max((self.window_height - self.state.height), top) top = min(0, top) return Rectangle( self.state.width, self.state.height, Vector(left + self.state.width // 2, top + self.state.height // 2))
def __init__(self, **options): """ Options: x, y, font, color, restricted, maxlength, prompt """ self.options = Config( options, ['x', '0'], ['y', '0'], ['font', 'pygame.font.Font(None, 32)'], ['color', '(0,0,0)'], [ 'restricted', '\'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLM' 'NOPQRSTUVWXYZ0123456789!"#$%&\\\'()' '*+,-./:;<=>?@[\]^_`{|}~\'' ], ['maxlength', '-1'], ['prompt', '\'\'']) self.x = self.options.x self.y = self.options.y self.font = self.options.font self.color = self.options.color self.restricted = self.options.restricted self.maxlength = self.options.maxlength self.prompt = self.options.prompt self.value = '' self.shifted = False self.is_focused = False self.rect = Rectangle(150, 32, Vector(self.x + 75, self.y + 16))
def get_containing_rectangle(self): width = max(self.width, self.text_box.width) height = max(self.height, self.puck.radius * 2) + \ self.text_box.height return Rectangle(width, height, self.position + Vector(0, -self.text_box.height / 2))
def test_get_hitmask(self): rect = Rectangle(2, 2, (1, 1)) image = pygame.Surface((2, 2)) self.assertEqual(get_hitmask(rect, image, 0), [[True, True], [True, True]])
def move(self, translation): Rectangle.move(self, translation) self.sync_position()
def get_containing_rectangle(self): width = self.width + self.text_box.width height = max(self.height, self.text_box.height) return Rectangle(width, height, self.position + Vector(self.text_box.width / 2, 0))
class LevelDesign: GAME_MEASURES = [WIDTH, HEIGHT, WIDTH - WIDTH // 4, HEIGHT] def __init__(self): self.world = [] self.lights = [] self.swinging_lights = [] # this is the block according to which the view will move self.observer = Block((0, 0, 0), WIDTH, HEIGHT, 0, 0) self.setup_menu_camera() self.setup_text_boxes() self.setup_buttons() self.set_up_boundaries() Light.set_up_surfaces(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1]) self.settings = Settings(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1], MUSIC_IN_GAME1, DEFAULT_START_POSITION) def setup_menu_camera(self): # this is the menu bar self.menu = Rectangle(WIDTH // 4, HEIGHT, (WIDTH - WIDTH // 4 + (WIDTH // 4) // 2, HEIGHT // 2)) self.camera = Camera(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1], WIDTH - WIDTH // 4, HEIGHT) def setup_text_boxes(self): self.block_textbox = eztext.Input(maxlength=15, color=(255, 0, 0), prompt='w, h, c: ', x=WIDTH - WIDTH // 4 + 10, y=0, font=pygame.font.Font(None, 30)) self.sawblock_textbox = eztext.Input(maxlength=5, color=(255, 0, 0), prompt='l: ', x=WIDTH - WIDTH // 4 + 10, y=70, font=pygame.font.Font(None, 30)) self.textboxes = [self.block_textbox, self.sawblock_textbox] def setup_buttons(self): self.rectangle_button = Button((WIDTH - WIDTH // 4 + 10, 30), (150, 30), "Spawn Rect", (0, 0, 0), (255, 0, 0)) self.sawblock_button = Button((WIDTH - WIDTH // 4 + 10, 100), (150, 30), "Spawn Saw", (0, 0, 0), (255, 0, 0)) self.light_button = Button((WIDTH - WIDTH // 4 + 10, 140), (180, 30), "Spawn Light", (0, 0, 0), (255, 0, 0)) self.swinginglight_button = Button((WIDTH - WIDTH // 4 + 10, 180), (180, 30), "Swinging Light", (0, 0, 0), (255, 0, 0)) self.expand_up = Button((WIDTH - WIDTH // 4 + 10, HEIGHT - 90), (100, 30), "Expand^", (0, 0, 0), (255, 255, 255)) self.expand_right = Button((WIDTH - WIDTH // 4 + 10, HEIGHT - 30), (100, 30), "Expand>", (0, 0, 0), (255, 255, 255)) self.retract_left = Button((WIDTH - WIDTH // 4 + 110, HEIGHT - 30), (100, 30), "Retract<", (0, 0, 0), (255, 255, 255)) self.retract_down = Button((WIDTH - WIDTH // 4 + 110, HEIGHT - 90), (100, 30), "Retract\/", (0, 0, 0), (255, 255, 255)) self.delete_button = Button((WIDTH - WIDTH // 4 + 65, HEIGHT - 140), (100, 30), "Despawn", (0, 0, 0), (255, 255, 255)) self.save_button = Button((WIDTH - WIDTH // 4 + 65, HEIGHT - 200), (100, 30), "Save", (0, 0, 0), (255, 255, 255)) self.load_button = Button((WIDTH - WIDTH // 4 + 65, HEIGHT - 280), (100, 30), "Load", (0, 0, 0), (255, 255, 255)) self.quit = Button((WIDTH - WIDTH // 4 + 65, HEIGHT - 340), (100, 30), "Quit", (0, 0, 0), (255, 255, 255)) self.buttons = [self.rectangle_button, self.sawblock_button, self.light_button, self.expand_up, self.expand_right, self.retract_down, self.retract_left, self.delete_button, self.save_button, self.load_button, self.quit, self.swinginglight_button] def move_blocks_down(self): """first 4 blocks are always the boundaries""" for index, item in enumerate(self.world): if index >= 4: if isinstance(item, Block): item.rect.center = Vector(item.rect.center[0], item.rect.center[1] + 32) elif isinstance(item, SawBlock): item.y += 32 item.rect.center = Vector(item.rect.center[0], item.rect.center[1] + 32) elif isinstance(item, Light): item.update_light_position(item.x, item.y + 32) def resize_game_field(self, action): if action == EXPAND_FIELD_RIGHT: LevelDesign.GAME_MEASURES[0] += 32 elif action == EXPAND_FIELD_UP: LevelDesign.GAME_MEASURES[1] += 32 self.move_blocks_down() elif action == RETRACT_FIELD_LEFT: LevelDesign.GAME_MEASURES[0] -= 32 elif action == RETRACT_FIELD_DOWN: LevelDesign.GAME_MEASURES[1] -= 32 else: return self.camera = Camera(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1], LevelDesign.GAME_MEASURES[2], LevelDesign.GAME_MEASURES[3]) self.settings.width = LevelDesign.GAME_MEASURES[0] self.settings.height = LevelDesign.GAME_MEASURES[1] self.set_up_boundaries() self.world = self.world[-4:] + self.world[4:-4] Light.update_surfaces(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1]) for light in self.lights: light.update_obstacles(self.world) light.update_local_surfaces() def save(self): world = json.dumps(self.world, cls=Encoder) light = json.dumps(self.lights, cls=Encoder) settings = json.dumps(self.settings, cls=Encoder) swinging_lights = json.dumps(self.swinging_lights, cls=Encoder) with open("../Files/Levels/level2.btmn", "w") as level: print(world, file=level) print(light, file=level) print(settings, file=level) print(swinging_lights, file=level) def load(self): with open("../Files/Levels/level2.btmn", "r") as level: world = level.readline() light = level.readline() settings = level.readline() swinging_lights = level.readline() self.settings = json.loads(settings, cls=Decoder) LevelDesign.GAME_MEASURES[0] = self.settings.width LevelDesign.GAME_MEASURES[1] = self.settings.height Light.set_up_surfaces(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1]) self.camera = Camera(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1], LevelDesign.GAME_MEASURES[2], LevelDesign.GAME_MEASURES[3]) self.world = json.loads(world, cls=Decoder) self.lights = json.loads(light, cls=Decoder) self.swinging_lights = json.loads(swinging_lights, cls=Decoder) for light in self.lights + self.swinging_lights: light.update_obstacles(self.world) def spawn_block(self, information, camera, colour=(0, 0, 0)): """information contains, width, height, tag""" self.world.append(Block(colour, information[0], information[1], camera.reverse_apply((32, 32))[0], camera.reverse_apply((32, 32))[1], information[2])) for light in self.lights: light.update_obstacles(self.world) def spawn_saw_block(self, length, camera): self.world.append(SawBlock(camera.reverse_apply((50, 0))[0], camera.reverse_apply((50, 0))[1], length)) def spawn_light(self, radius, camera): self.lights.append(Light(camera.reverse_apply((50, 50))[0], camera.reverse_apply((50, 50))[1], radius, self.world)) def spawn_swinging_light(self, rope_length, camera): coordinates = camera.reverse_apply((50, 50)) self.swinging_lights.append(SwingingLight(coordinates[0], coordinates[1], rope_length, self.world)) def de_spawn(self, index_object): if index_object == NO_OBJECT_SELECTED: return False index, object_type = index_object if object_type == OBJECT: self.world.pop(index) elif object_type == OBJECT_LIGHT: self.lights.pop(index) elif object_type == OBJECT_SWINGING_LIGHT: self.swinging_lights.pop(index) return True def decode_textbox(self, textbox_input, context): try: value = textbox_input.value.split() if context == OBJECT_BLOCK: if len(value) == 3: return int(value[0]), int(value[1]), TAG_WALL else: return int(value[0]), int(value[1]), TAG_GROUND elif context == OBJECT_SAW_BLOCK or context == OBJECT_LIGHT or\ context == OBJECT_SWINGING_LIGHT: return int(value[0]) # if we can't decode it except ValueError: raise DecodingFailure except IndexError: return def selector(self, mouse_position, events): """determine which object is selected""" for event in events: if event.type == pygame.MOUSEBUTTONDOWN: for index, piece in enumerate(self.world): if index < 3: continue elif piece.rect.is_point_in_body(mouse_position, self.camera): return index, OBJECT for index, light in enumerate(self.lights): if light.collide( self.camera.reverse_apply(mouse_position)): return index, OBJECT_LIGHT for index, swinging_light in enumerate(self.swinging_lights): if swinging_light.collide( self.camera.reverse_apply(mouse_position)): return index, OBJECT_SWINGING_LIGHT return NO_OBJECT_SELECTED def draw_light(self, screen): for light in self.lights: light.draw_shadow(self.camera) light.draw_light(self.camera) def draw(self, screen): screen.fill((255, 255, 255)) Light.nullify_shadow() Light.nullify_light() self.draw_light(screen) for piece in self.world: piece.draw(screen, self.camera) for swinging_light in self.swinging_lights: swinging_light.draw(screen, self.camera) Light.draw_everything(screen) self.menu.draw(screen, (0, 255, 0)) for button in self.buttons: button.draw(screen) for text_box in self.textboxes: text_box.draw(screen) self.block_textbox.draw(screen) pygame.display.update() def set_up_boundaries(self): self.world.append(Block((0, 0, 0), LevelDesign.GAME_MEASURES[0], 32, 0, 0, TAG_GROUND)) self.world.append(Block((0, 0, 0), LevelDesign.GAME_MEASURES[0], 32, 0, LevelDesign.GAME_MEASURES[1] - 32, TAG_GROUND)) self.world.append(Block((0, 0, 0), 32, LevelDesign.GAME_MEASURES[1], 0, 0, TAG_WALL)) self.world.append(Block((0, 0, 0), 32, LevelDesign.GAME_MEASURES[1], LevelDesign.GAME_MEASURES[0] - 32, 0, TAG_WALL)) def move_block(self, index, position): self.world[index].rect.position = \ Vector(self.camera.reverse_apply(position)) self.world[index].x = self.camera.reverse_apply(position)[0] -\ self.world[index].width / 2 self.world[index].y = self.camera.reverse_apply(position)[1] -\ self.world[index].height / 2 for light in self.lights + self.swinging_lights: light.update_obstacles(self.world) def move_saw_block(self, index, position): self.world[index].rect.center = \ Vector(self.camera.reverse_apply(position)) self.world[index].x = self.camera.reverse_apply(position)[0] self.world[index].y = self.world[index].rect.position[1] - \ self.world[index].rope_height - 15 def move_lights(self, index, position): self.lights[index].\ update_light_position(self.camera.reverse_apply(position)[0], self.camera.reverse_apply(position)[1]) def move_swinging_lights(self, index, position): self.swinging_lights[index].\ update_position(self.camera.reverse_apply(position)[0], self.camera.reverse_apply(position)[1]) def move(self, index_object, screen): """do the moving itself""" if index_object == NO_OBJECT_SELECTED: return index, object = index_object while True: self.draw(screen) events = pygame.event.get() mouse_position = pygame.mouse.get_pos() if object == OBJECT: if isinstance(self.world[index], Block): self.move_block(index, mouse_position) elif isinstance(self.world[index], SawBlock): self.move_saw_block(index, mouse_position) elif object == OBJECT_LIGHT: self.move_lights(index, mouse_position) elif object == OBJECT_SWINGING_LIGHT: self.move_swinging_lights(index, mouse_position) for event in events: if event.type == pygame.MOUSEBUTTONUP: return def set_focus(self, mouse_position): """set focus to a textbox so you write only in that one""" for text_box in self.textboxes: text_box.is_focused = False if text_box.rect.is_point_in_body(mouse_position): text_box.is_focused = True def update(self): for swinging_light in self.swinging_lights: swinging_light.update() def button_management(self, mouse_position, events): try: if self.rectangle_button.is_pressed(mouse_position, events): decoded = self.decode_textbox(self.block_textbox, OBJECT_BLOCK) if decoded is not None: self.spawn_block(decoded, self.camera) elif self.sawblock_button.is_pressed(mouse_position, events): decoded = self.decode_textbox(self.sawblock_textbox, OBJECT_SAW_BLOCK) if decoded is not None: self.spawn_saw_block(decoded, self.camera) elif self.swinginglight_button.is_pressed(mouse_position, events): decoded = self.decode_textbox(self.sawblock_textbox, OBJECT_SAW_BLOCK) if decoded is not None: self.spawn_swinging_light(decoded, self.camera) elif self.light_button.is_pressed(mouse_position, events): self.spawn_light(LIGHT_RADIUS, self.camera) elif self.expand_up.is_pressed(mouse_position, events): self.resize_game_field(EXPAND_FIELD_UP) elif self.expand_right.is_pressed(mouse_position, events): self.resize_game_field(EXPAND_FIELD_RIGHT) elif self.retract_down.is_pressed(mouse_position, events): self.resize_game_field(RETRACT_FIELD_DOWN) elif self.retract_left.is_pressed(mouse_position, events): self.resize_game_field(RETRACT_FIELD_LEFT) elif self.quit.is_pressed(mouse_position, events): sys.exit() elif self.delete_button.is_pressed(mouse_position, events): while True: mouse_position = pygame.mouse.get_pos() events = pygame.event.get() if self.de_spawn(self.selector(mouse_position, events)): return elif self.save_button.is_pressed(mouse_position, events): self.save() elif self.load_button.is_pressed(mouse_position, events): self.load() except DecodingFailure: return
def move(self, translation): Rectangle.move(self, translation) self.sync_position() self.puck.move(translation) self.text_box.move(translation)
def rotate_saw(self, time): self.image = transform.rotate(self.saw_image_master, self.rotation) self.rect = Rectangle.get_rect(self.image, self.center_old) self.rotation += 300 * time / 1000 if self.rotation > 360: self.rotation = self.step
class LevelDesign: GAME_MEASURES = [WIDTH, HEIGHT, WIDTH - WIDTH // 4, HEIGHT] def __init__(self): self.world = [] self.lights = [] self.swinging_lights = [] # this is the block according to which the view will move self.observer = Block((0, 0, 0), WIDTH, HEIGHT, 0, 0) self.setup_menu_camera() self.setup_text_boxes() self.setup_buttons() self.set_up_boundaries() Light.set_up_surfaces(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1]) self.settings = Settings(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1], MUSIC_IN_GAME1, DEFAULT_START_POSITION) def setup_menu_camera(self): # this is the menu bar self.menu = Rectangle(WIDTH // 4, HEIGHT, (WIDTH - WIDTH // 4 + (WIDTH // 4) // 2, HEIGHT // 2)) self.camera = Camera(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1], WIDTH - WIDTH // 4, HEIGHT) def setup_text_boxes(self): self.block_textbox = eztext.Input(maxlength=15, color=(255, 0, 0), prompt='w, h, c: ', x=WIDTH - WIDTH // 4 + 10, y=0, font=pygame.font.Font(None, 30)) self.sawblock_textbox = eztext.Input(maxlength=5, color=(255, 0, 0), prompt='l: ', x=WIDTH - WIDTH // 4 + 10, y=70, font=pygame.font.Font(None, 30)) self.textboxes = [self.block_textbox, self.sawblock_textbox] def setup_buttons(self): self.rectangle_button = Button((WIDTH - WIDTH // 4 + 10, 30), (150, 30), "Spawn Rect", (0, 0, 0), (255, 0, 0)) self.sawblock_button = Button((WIDTH - WIDTH // 4 + 10, 100), (150, 30), "Spawn Saw", (0, 0, 0), (255, 0, 0)) self.light_button = Button((WIDTH - WIDTH // 4 + 10, 140), (180, 30), "Spawn Light", (0, 0, 0), (255, 0, 0)) self.swinginglight_button = Button((WIDTH - WIDTH // 4 + 10, 180), (180, 30), "Swinging Light", (0, 0, 0), (255, 0, 0)) self.expand_up = Button((WIDTH - WIDTH // 4 + 10, HEIGHT - 90), (100, 30), "Expand^", (0, 0, 0), (255, 255, 255)) self.expand_right = Button((WIDTH - WIDTH // 4 + 10, HEIGHT - 30), (100, 30), "Expand>", (0, 0, 0), (255, 255, 255)) self.retract_left = Button((WIDTH - WIDTH // 4 + 110, HEIGHT - 30), (100, 30), "Retract<", (0, 0, 0), (255, 255, 255)) self.retract_down = Button((WIDTH - WIDTH // 4 + 110, HEIGHT - 90), (100, 30), "Retract\/", (0, 0, 0), (255, 255, 255)) self.delete_button = Button((WIDTH - WIDTH // 4 + 65, HEIGHT - 140), (100, 30), "Despawn", (0, 0, 0), (255, 255, 255)) self.save_button = Button((WIDTH - WIDTH // 4 + 65, HEIGHT - 200), (100, 30), "Save", (0, 0, 0), (255, 255, 255)) self.load_button = Button((WIDTH - WIDTH // 4 + 65, HEIGHT - 280), (100, 30), "Load", (0, 0, 0), (255, 255, 255)) self.quit = Button((WIDTH - WIDTH // 4 + 65, HEIGHT - 340), (100, 30), "Quit", (0, 0, 0), (255, 255, 255)) self.buttons = [ self.rectangle_button, self.sawblock_button, self.light_button, self.expand_up, self.expand_right, self.retract_down, self.retract_left, self.delete_button, self.save_button, self.load_button, self.quit, self.swinginglight_button ] def move_blocks_down(self): """first 4 blocks are always the boundaries""" for index, item in enumerate(self.world): if index >= 4: if isinstance(item, Block): item.rect.center = Vector(item.rect.center[0], item.rect.center[1] + 32) elif isinstance(item, SawBlock): item.y += 32 item.rect.center = Vector(item.rect.center[0], item.rect.center[1] + 32) elif isinstance(item, Light): item.update_light_position(item.x, item.y + 32) def resize_game_field(self, action): if action == EXPAND_FIELD_RIGHT: LevelDesign.GAME_MEASURES[0] += 32 elif action == EXPAND_FIELD_UP: LevelDesign.GAME_MEASURES[1] += 32 self.move_blocks_down() elif action == RETRACT_FIELD_LEFT: LevelDesign.GAME_MEASURES[0] -= 32 elif action == RETRACT_FIELD_DOWN: LevelDesign.GAME_MEASURES[1] -= 32 else: return self.camera = Camera(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1], LevelDesign.GAME_MEASURES[2], LevelDesign.GAME_MEASURES[3]) self.settings.width = LevelDesign.GAME_MEASURES[0] self.settings.height = LevelDesign.GAME_MEASURES[1] self.set_up_boundaries() self.world = self.world[-4:] + self.world[4:-4] Light.update_surfaces(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1]) for light in self.lights: light.update_obstacles(self.world) light.update_local_surfaces() def save(self): world = json.dumps(self.world, cls=Encoder) light = json.dumps(self.lights, cls=Encoder) settings = json.dumps(self.settings, cls=Encoder) swinging_lights = json.dumps(self.swinging_lights, cls=Encoder) with open("../Files/Levels/level2.btmn", "w") as level: print(world, file=level) print(light, file=level) print(settings, file=level) print(swinging_lights, file=level) def load(self): with open("../Files/Levels/level2.btmn", "r") as level: world = level.readline() light = level.readline() settings = level.readline() swinging_lights = level.readline() self.settings = json.loads(settings, cls=Decoder) LevelDesign.GAME_MEASURES[0] = self.settings.width LevelDesign.GAME_MEASURES[1] = self.settings.height Light.set_up_surfaces(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1]) self.camera = Camera(LevelDesign.GAME_MEASURES[0], LevelDesign.GAME_MEASURES[1], LevelDesign.GAME_MEASURES[2], LevelDesign.GAME_MEASURES[3]) self.world = json.loads(world, cls=Decoder) self.lights = json.loads(light, cls=Decoder) self.swinging_lights = json.loads(swinging_lights, cls=Decoder) for light in self.lights + self.swinging_lights: light.update_obstacles(self.world) def spawn_block(self, information, camera, colour=(0, 0, 0)): """information contains, width, height, tag""" self.world.append( Block(colour, information[0], information[1], camera.reverse_apply((32, 32))[0], camera.reverse_apply((32, 32))[1], information[2])) for light in self.lights: light.update_obstacles(self.world) def spawn_saw_block(self, length, camera): self.world.append( SawBlock( camera.reverse_apply((50, 0))[0], camera.reverse_apply((50, 0))[1], length)) def spawn_light(self, radius, camera): self.lights.append( Light( camera.reverse_apply((50, 50))[0], camera.reverse_apply((50, 50))[1], radius, self.world)) def spawn_swinging_light(self, rope_length, camera): coordinates = camera.reverse_apply((50, 50)) self.swinging_lights.append( SwingingLight(coordinates[0], coordinates[1], rope_length, self.world)) def de_spawn(self, index_object): if index_object == NO_OBJECT_SELECTED: return False index, object_type = index_object if object_type == OBJECT: self.world.pop(index) elif object_type == OBJECT_LIGHT: self.lights.pop(index) elif object_type == OBJECT_SWINGING_LIGHT: self.swinging_lights.pop(index) return True def decode_textbox(self, textbox_input, context): try: value = textbox_input.value.split() if context == OBJECT_BLOCK: if len(value) == 3: return int(value[0]), int(value[1]), TAG_WALL else: return int(value[0]), int(value[1]), TAG_GROUND elif context == OBJECT_SAW_BLOCK or context == OBJECT_LIGHT or\ context == OBJECT_SWINGING_LIGHT: return int(value[0]) # if we can't decode it except ValueError: raise DecodingFailure except IndexError: return def selector(self, mouse_position, events): """determine which object is selected""" for event in events: if event.type == pygame.MOUSEBUTTONDOWN: for index, piece in enumerate(self.world): if index < 3: continue elif piece.rect.is_point_in_body(mouse_position, self.camera): return index, OBJECT for index, light in enumerate(self.lights): if light.collide( self.camera.reverse_apply(mouse_position)): return index, OBJECT_LIGHT for index, swinging_light in enumerate(self.swinging_lights): if swinging_light.collide( self.camera.reverse_apply(mouse_position)): return index, OBJECT_SWINGING_LIGHT return NO_OBJECT_SELECTED def draw_light(self, screen): for light in self.lights: light.draw_shadow(self.camera) light.draw_light(self.camera) def draw(self, screen): screen.fill((255, 255, 255)) Light.nullify_shadow() Light.nullify_light() self.draw_light(screen) for piece in self.world: piece.draw(screen, self.camera) for swinging_light in self.swinging_lights: swinging_light.draw(screen, self.camera) Light.draw_everything(screen) self.menu.draw(screen, (0, 255, 0)) for button in self.buttons: button.draw(screen) for text_box in self.textboxes: text_box.draw(screen) self.block_textbox.draw(screen) pygame.display.update() def set_up_boundaries(self): self.world.append( Block((0, 0, 0), LevelDesign.GAME_MEASURES[0], 32, 0, 0, TAG_GROUND)) self.world.append( Block((0, 0, 0), LevelDesign.GAME_MEASURES[0], 32, 0, LevelDesign.GAME_MEASURES[1] - 32, TAG_GROUND)) self.world.append( Block((0, 0, 0), 32, LevelDesign.GAME_MEASURES[1], 0, 0, TAG_WALL)) self.world.append( Block((0, 0, 0), 32, LevelDesign.GAME_MEASURES[1], LevelDesign.GAME_MEASURES[0] - 32, 0, TAG_WALL)) def move_block(self, index, position): self.world[index].rect.position = \ Vector(self.camera.reverse_apply(position)) self.world[index].x = self.camera.reverse_apply(position)[0] -\ self.world[index].width / 2 self.world[index].y = self.camera.reverse_apply(position)[1] -\ self.world[index].height / 2 for light in self.lights + self.swinging_lights: light.update_obstacles(self.world) def move_saw_block(self, index, position): self.world[index].rect.center = \ Vector(self.camera.reverse_apply(position)) self.world[index].x = self.camera.reverse_apply(position)[0] self.world[index].y = self.world[index].rect.position[1] - \ self.world[index].rope_height - 15 def move_lights(self, index, position): self.lights[index].\ update_light_position(self.camera.reverse_apply(position)[0], self.camera.reverse_apply(position)[1]) def move_swinging_lights(self, index, position): self.swinging_lights[index].\ update_position(self.camera.reverse_apply(position)[0], self.camera.reverse_apply(position)[1]) def move(self, index_object, screen): """do the moving itself""" if index_object == NO_OBJECT_SELECTED: return index, object = index_object while True: self.draw(screen) events = pygame.event.get() mouse_position = pygame.mouse.get_pos() if object == OBJECT: if isinstance(self.world[index], Block): self.move_block(index, mouse_position) elif isinstance(self.world[index], SawBlock): self.move_saw_block(index, mouse_position) elif object == OBJECT_LIGHT: self.move_lights(index, mouse_position) elif object == OBJECT_SWINGING_LIGHT: self.move_swinging_lights(index, mouse_position) for event in events: if event.type == pygame.MOUSEBUTTONUP: return def set_focus(self, mouse_position): """set focus to a textbox so you write only in that one""" for text_box in self.textboxes: text_box.is_focused = False if text_box.rect.is_point_in_body(mouse_position): text_box.is_focused = True def update(self): for swinging_light in self.swinging_lights: swinging_light.update() def button_management(self, mouse_position, events): try: if self.rectangle_button.is_pressed(mouse_position, events): decoded = self.decode_textbox(self.block_textbox, OBJECT_BLOCK) if decoded is not None: self.spawn_block(decoded, self.camera) elif self.sawblock_button.is_pressed(mouse_position, events): decoded = self.decode_textbox(self.sawblock_textbox, OBJECT_SAW_BLOCK) if decoded is not None: self.spawn_saw_block(decoded, self.camera) elif self.swinginglight_button.is_pressed(mouse_position, events): decoded = self.decode_textbox(self.sawblock_textbox, OBJECT_SAW_BLOCK) if decoded is not None: self.spawn_swinging_light(decoded, self.camera) elif self.light_button.is_pressed(mouse_position, events): self.spawn_light(LIGHT_RADIUS, self.camera) elif self.expand_up.is_pressed(mouse_position, events): self.resize_game_field(EXPAND_FIELD_UP) elif self.expand_right.is_pressed(mouse_position, events): self.resize_game_field(EXPAND_FIELD_RIGHT) elif self.retract_down.is_pressed(mouse_position, events): self.resize_game_field(RETRACT_FIELD_DOWN) elif self.retract_left.is_pressed(mouse_position, events): self.resize_game_field(RETRACT_FIELD_LEFT) elif self.quit.is_pressed(mouse_position, events): sys.exit() elif self.delete_button.is_pressed(mouse_position, events): while True: mouse_position = pygame.mouse.get_pos() events = pygame.event.get() if self.de_spawn(self.selector(mouse_position, events)): return elif self.save_button.is_pressed(mouse_position, events): self.save() elif self.load_button.is_pressed(mouse_position, events): self.load() except DecodingFailure: return
from pygame.math import Vector2 as Vector from motions import Motion from ragdoll import HumanRagdoll from basicshapes import Rectangle pygame.init() screen = pygame.display.set_mode((1000, 1000)) clock = pygame.time.Clock() ragdoll = HumanRagdoll("Batman") ragdoll.move(Vector((500, 500))) motion = Motion(ragdoll) ground = Rectangle(1000, 70, Vector(500, 1000)) # for body_part in list(ragdoll.body_parts.values())[::-1]: # control.left_button_selectable.append(body_part) anchor = Vector(0, 0) # def cursor_controll(body, anchor): # body.pull_on_anchor(anchor, cursor_location - anchor) # anchor = cursor_location ragdoll_velosity = Vector(0, 0) cursor_left_button_is_down = False cursor_selected_body = None current_frame = 0 current_part = None