def calculate_reward(self, snake_bodyAI, snake_bodyPlayer, fruit_pos): # Player hits snake_AI's body for block in snake_bodyAI[1:]: if block == snake_bodyPlayer[0]: return 20 # Snake_AI's head hits itself if (len(snake_bodyAI) > 6): if Vector2.distance_to(snake_bodyAI[-1], snake_bodyAI[0]) < 3 or Vector2.distance_to( snake_bodyAI[-2], snake_bodyAI[0]) < 3: return -100 for block in snake_bodyAI[1:]: if block == snake_bodyAI[0]: return -100 # Snake_AI's head near player's body for block in snake_bodyPlayer: if Vector2.distance_to(snake_bodyAI[0], block) <= 3: return -100 # Snake_AI's head on apple position if (Vector2.distance_to(snake_bodyAI[0], fruit_pos) == 0): return 50 # Empty square else: return -10
def qix(self, pos: Vector2, facing: float, size: float) -> None: """ Draws the Qix :param pos: Current position :param facing: Facing direction :param size: Size of object :return: None """ draw_color = (255, 0, 0) delta = Vector2(0, size / 2) if pos.distance_to( self.prev_qix[-1][0]) >= 0.01 or facing - self.prev_qix[-1][ 1] > 0.01 or facing - self.prev_qix[-1][1] < -0.01: self.qix_update(pos, facing) offset = delta.rotate(facing) start = (pos + offset) * self.scale + Vector2(self.offset) end = (pos - offset) * self.scale + Vector2(self.offset) pygame.draw.aaline(self.surface, draw_color, start, end, 2) self.qix_lines = [[start, end]] for (pos, facing, draw_color) in self.prev_qix: offset = delta.rotate(facing) start = (pos + offset) * self.scale + Vector2(self.offset) end = (pos - offset) * self.scale + Vector2(self.offset) pygame.draw.aaline(self.surface, draw_color, start, end, 2) self.qix_lines.append([start, end])
def main(): pygame.init() clock = pygame.time.Clock() screen = pygame.display.set_mode((screen_width, screen_height)) background = pygame.Surface(screen.get_size()) background.fill(bg_color) background.convert() running = True stage = 6 player, entities, edibles, clickables = reset(0, stage) while running: # restart if the player has eaten everything if len(edibles) == 0 or player.sfd: if not player.sfd: stage += 1 if stage > max_difficulty: stage = max_difficulty player, entities, edibles, clickables = reset(player.score, stage) time = clock.tick( FPS) # get the time passed since the last frame (in milliseconds) dt = time / 1000 # blit the background screen.blit(background, (0, 0)) # event handling for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.MOUSEBUTTONDOWN: pos = Vec(pygame.mouse.get_pos()) for c in clickables: if pos.distance_to(c.pos) < c.xsize + grace_distance: player.target = c # The final clickable knows about the player if player.target is not None: player.target.is_clicked = True player.target.target = player elif event.type == pygame.MOUSEBUTTONUP: if player.target is not None: player.target.is_clicked = False player.target.target = None player.target = None for entity in entities: entity.update(dt, entities) # Kill all entities scheduled for destruction entities = [e for e in entities if not e.sfd] edibles = [e for e in edibles if not e.sfd] clickables = [e for e in clickables if not e.sfd] for entity in entities: entity.draw(screen) pygame.display.update()
def get_close_entity_in_state(self, name, states, location: Vector2, radius=20.): """ Find an entity within range of a location that is in one of the states provided. """ for entity in self.entities.values(): if entity.name == name: for state in states: if entity.brain.active_state.name == state: distance = location.distance_to(entity.location) if distance < radius: return entity return None
def get_closest_entity(self, name, location: Vector2, radius=20.): """ Find the closest entity within range of a location """ close_entities = [] for entity in self.entities.values(): if name is None or entity.name == name: distance = location.distance_to(entity.location) if distance < radius: close_entities.append((distance, entity)) # Return the closest of the entities within range. if len(close_entities) > 0: close_entities = sorted(close_entities, key=lambda e: e[0]) distance, closest_entity = close_entities[0] return closest_entity return None
def get_close_entity(self, name, location: Vector2, radius=20., ignore_id=None): """ Finds the first entity within range of a location """ for entity in self.entities.values(): # If an ignore_id is passed, ignore the entity with that id. if ignore_id is not None and entity.id == ignore_id: continue if name is None or entity.name == name: distance = location.distance_to(entity.location) if distance < radius: return entity return None
def is_home(self, pos: Vector2) -> bool: for ent, (home, mov) in self.world.get_components(Home, Movable): if pos.distance_to(mov.position) < CONTACT_DISTANCE: return True return False
class GraplingHook(): 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 calculate_angle(self): self.angle = self.rope.angle_to(self.limit) def retract(self, timer): if self.distance > self.distance_limit: self.rect.advance(self.rope.x * 700 * (timer / 1000), self.rope.y * 700 * (timer / 1000)) self.x += self.rope.x * 700 * (timer / 1000) self.y += self.rope.y * 700 * (timer / 1000) self.calculate_rope() else: self.swing() def calculate_rope(self): self.hook = Vector(self.aim) self.player = Vector(self.rect.center[0], self.rect.center[1]) self.distance = self.hook.distance_to(self.player) self.rope = self.hook - self.player self.rope = self.rope.normalize() 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 def shoot(self, timer): for element in self.stop_rect: class Collide: def __init__(self, rect, hitmask): self.rect = rect self.hitmask = hitmask collider = Collide(self.hook_rect, self.hitmask) if not collide(collider, element): self.hook_rect.advance(self.rope.x * 500 * (timer / 1000), self.rope.y * 500 * (timer / 1000)) else: if self.calculate_pivot: self.hook_rect.rotate(90 - self.angle) self.aim = (self.hook_rect.vertices[0].x + self.hook_rect.vertices[1].x) // 2, \ (self.hook_rect.vertices[0].y + self.hook_rect.vertices[1].y) // 2 self.bob = Pendulum(90 - self.angle, self.distance_limit, self.aim) self.calculate_pivot = False self.shooter = False 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 functionality(self, events, world): for event in events: if event.type == pygame.MOUSEMOTION and self.should_aim: self.aim = pygame.mouse.get_pos() if event.type == pygame.MOUSEBUTTONUP and self.should_aim: for collider in world: if collider.rect.is_point_in_body(self.aim): self.stop_rect = world self.shooter = True self.calculate_rope() self.calculate_angle() if event.type == pygame.KEYUP: if event.key == pygame.K_LCTRL: self.should_release = True self.should_retract = False def release(self, timer): self.calculate_rope() self.rect.advance((-self.rope.x * 10 - (sin(self.bob.theta) * int(self.bob.d_theta))) * 40 * (timer / 1000), (-self.rope.y * 10 + self.rope.y * (30 - self.time)) * 15 * (timer / 1000)) self.time += 0.8 def draw(self, screen, camera): if not self.should_release: pygame.draw.aaline(screen, (0, 0, 0), camera.apply(self.rect.center), camera.apply(self.aim)) screen.blit(self.image, camera.apply((self.x, self.y))) screen.blit( self.hook_image, camera.apply((self.hook_rect.center[0] - 20, self.hook_rect.center[1] - 20))) def reposition(self, coordinates): self.rect.center = Vector(coordinates)