예제 #1
0
def draw(self, packet):
    my_car = packet.game_cars[self.index]
    car_location = Vector2(my_car.physics.location.x, my_car.physics.location.y)
    ball_location = Vector2(packet.game_ball.physics.location.x, packet.game_ball.physics.location.y)

    
    # color
    color = self.renderer.create_color(255, 255, 255, 255)
    white_color = self.renderer.create_color(255, 255, 255, 255)
    x = 5
    y = 10
    text_size = 1
    if my_car.team == 0:
        x = 5
        color = self.renderer.create_color(255, 22, 138, 255) # blue
    else:
        x = 150
        color = self.renderer.create_color(255, 255, 127, 80) # orange
        

    # drawing
    self.renderer.draw_string_2d(x, y, text_size, text_size, self.car_status, color)
    self.renderer.draw_string_2d(x, y+10, text_size, text_size, str(Vector2(car_location.x - ball_location.x, car_location.y - ball_location.y).magnitude()), color)
    self.renderer.draw_string_2d(x, y+20, text_size, text_size, 'boost: '+str(my_car.boost), color)
    self.renderer.draw_string_2d(x, y+30, text_size, text_size, 'Jumps: '+str(self.jumps), color)
    self.renderer.draw_string_2d(x, y+40, text_size, text_size, 'Z: '+str(my_car.physics.location.z), color)
    self.renderer.draw_string_2d(x, y+50, text_size, text_size, 'speed: '+str(self.average_xy_speed), color)
    if self.car_status == 'kick_ball': self.renderer.draw_string_2d(x, y+60, text_size, text_size, 'TimeTillHit: '+str(kick_ball.prediction_timer), color)
    if self.car_status == 'clear_ball': self.renderer.draw_string_2d(x, y+60, text_size, text_size, 'TimeTillHit: '+str(clear_ball.prediction_timer), color)
예제 #2
0
파일: world.py 프로젝트: jcharra/StreetCatz
 def get_closest_entity(self, fromLocation, targetClass, range=1000, validityTest=None):
     closestDist = range
     closestEntity = None
     for ent in self.entities.itervalues():
         if isinstance(ent, targetClass) and Vector2.get_distance(ent.location, fromLocation) < closestDist:
             if not validityTest or validityTest(ent):
                 closestDist = Vector2.get_distance(ent.location, fromLocation)
                 closestEntity = ent
     return closestEntity
예제 #3
0
 def switchVehicle(self, vehicle):
     self.speed = 0.0
     if self.vehicle == vehicle:
         self.vehicle.move(STOP)
         self.vehicle = None
         self.location = vehicle.location + Vector2(-20,0)    
     elif self.vehicle == None and Vector2.get_distance(self.location, vehicle.location) <= 50:
         self.vehicle = vehicle
         self.vehicle.start()
예제 #4
0
def wrong_side(agent, packet):
    my_car = packet.game_cars[agent.index]
    car_location = Vector2(my_car.physics.location.x, my_car.physics.location.y)
    car_direction = get_car_facing_vector(my_car)
    ball_location = Vector2(packet.game_ball.physics.location.x, packet.game_ball.physics.location.y)
    goal = get_own_goal(agent, packet)
    difference = abs(difference_angles(Vector3(goal).to_2d().get_angle(), car_location.get_angle()))
    # double jump if on ground and straight and going good direction
    if agent.jumps == [] and my_car.physics.location.z < 17.1 and difference < 10 and get_xy_speed(agent, packet) > 1000 and my_car.boost > 50: agent.controller_state.boost = True
    if agent.jumps == [] and my_car.physics.location.z < 17.1 and difference < 10 and get_xy_speed(agent, packet) > 1000 and not agent.controller_state.boost: double_jump(agent)
    aim_to(agent, goal)
    agent.controller_state.throttle = 1.0
    # if in front of the ball+200 reset car status
    if my_car.team == (my_car.physics.location.y-ball_location.y > -2000):
        agent.car_status = 'none'
예제 #5
0
파일: world.py 프로젝트: jcharra/StreetCatz
 def get_closest_entity(self,
                        fromLocation,
                        targetClass,
                        range=1000,
                        validityTest=None):
     closestDist = range
     closestEntity = None
     for ent in self.entities.itervalues():
         if isinstance(ent, targetClass) and Vector2.get_distance(
                 ent.location, fromLocation) < closestDist:
             if not validityTest or validityTest(ent):
                 closestDist = Vector2.get_distance(ent.location,
                                                    fromLocation)
                 closestEntity = ent
     return closestEntity
예제 #6
0
def get_opponents_goal(agent):
    car = agent.car
    field_info = agent.get_field_info()
    goal = Vector2(0, 0)
    team = 1
    if field_info.goals[team].team_num == car.team: team = 0
    return Vector3(field_info.goals[team].location)
예제 #7
0
def kickoff(agent, packet):
    car = agent.car
    ball = agent.ball
    car_to_ball_magnitude = Vector2(car.pos.x - ball.pos.x, car.pos.y - ball.pos.y).magnitude()
    plus = 0

    
    agent.controller_state.boost = True
    agent.controller_state.throttle = 1.0

    # 255.97 and 3840.01
    if abs(car.pos.x) < 300:
        if car.team: plus = -car.pos.x/100
        else: plus = car.pos.x/100

    aim_to(agent, agent.ball.pos, (random()*2-1)+plus, )
    #print(car_location.x, car_location.y)
    # if me hit the ball stop kicking the ball
    if packet.game_ball.latest_touch.player_name == car.name and packet.game_info.seconds_elapsed - packet.game_ball.latest_touch.time_seconds < 1:
        agent.car_status = 'none'

    # If realy close to ball Jump
    if car_to_ball_magnitude < 500: double_jump(agent)
    # if on wrong side of the ball reset car status
    if car.team != (car.pos.y-agent.ball.pos.y > 0):
        agent.car_status = 'none'
    return agent
예제 #8
0
    def process(self, time_passed):
        if self.speed != 0.0:
            rotationDelta = self.rotationToDo * time_passed * self.rotation_speed
            if abs(self.rotationToDo - rotationDelta) < 5.0:
                rotationDelta = self.rotationToDo                
            self.rotationToDo -= rotationDelta
            self.rotation += rotationDelta
            
            heading_x = sin(self.rotation*pi/180.0)
            heading_y = cos(self.rotation*pi/180.0)
            heading = Vector2(heading_x, heading_y)
            
            self.location += heading * self.speed
            
            if not self.soundChannel.get_busy():
                self.soundChannel.play(self.drivingSound, -1)

        # no more rotation to do => handle next action
        if not self.rotationToDo and self.actionQueue:
            moveAction = self.actionQueue.pop()
            direction = moveAction.direction
            if direction in [LEFT, RIGHT]:
                self.steer(direction)
            elif direction == UP:
                self.accelerate()
            elif direction == DOWN:
                self.brake()
            elif direction == STOP:
                self.brakeHard()
예제 #9
0
    def __init__(self, centrePoint, width, height):
        self.id = "rectangle"

        try:
            self.x = centrePoint.x
            self.y = centrePoint.y

        except AttributeError:
            self.x = centrePoint[0]
            self.y = centrePoint[1]

        self.width = width
        self.height = height

        self.topLeft = Vector2(self.x - self.width, self.y + self.height)
        self.bottomRight = Vector2(self.x + self.width, self.y - self.height)
예제 #10
0
def get_car_facing_vector(car):
    pitch = float(car.rotation.pitch)
    yaw = float(car.rotation.yaw)

    facing_x = math.cos(pitch) * math.cos(yaw)
    facing_y = math.cos(pitch) * math.sin(yaw)

    return Vector2(facing_x, facing_y)
예제 #11
0
 def __init__(self, start_coordinates):
     self.image = pygame.image.load('../images/nedde.png').convert_alpha()
     self.location = start_coordinates
     
     self.speed = 40.0
     self.walking_direction = Vector2(0, 0)
     self.name = "player"
     self.foodAmount = 15
     self.vehicle = None
예제 #12
0
파일: world.py 프로젝트: jcharra/StreetCatz
 def __init__(self, display_size, background_image):
     self.entities = {}
     self.active_entities = {}
     self.entity_id = 0
     self.background = background_image
     self.dimension = self.background.get_size()
     self.focussed_entity = None
     self.display_size = display_size
     self.maximum_expansion = Vector2(*display_size).get_magnitude()
     self.minimapVisible = True
예제 #13
0
파일: clear_ball.py 프로젝트: Mart100/Mork
    def get_goal_angle(agent):
        ball = agent.ball
        ball_pos = clear_ball.ball_prediction.pos
        own_goal = agent.info.own_goal
        ball_to_pole1 = Vector2(893 + ball_pos.x, own_goal.y - ball_pos.y)
        ball_to_pole2 = Vector2(893 - ball_pos.x, own_goal.y - ball_pos.y)

        #draw lines
        agent.renderer.draw_line_3d(ball_pos.get_array(),
                                    own_goal.change('x', 893).get_array(),
                                    black(agent))
        agent.renderer.draw_line_3d(ball_pos.get_array(),
                                    own_goal.change('x', -893).get_array(),
                                    black(agent))

        # return angle
        return abs(
            difference_angles(ball_to_pole1.get_angle(),
                              ball_to_pole2.get_angle()) / 2)
예제 #14
0
    def collides(self, otherShape):
        if otherShape.id == "rectangle":
            #Do rectangle vs rectangle collision
            if otherShape.topLeft.x > self.bottomRight.x:
                return False
            elif otherShape.bottomRight.x < self.topLeft.x:
                return False
            elif otherShape.topLeft.y < self.bottomRight.y:
                return False
            elif otherShape.bottomRight.y > self.topLeft.y:
                return False

            else:
                return True

        elif otherShape.id == "circle":
            #Test each edge against the circle, and see if the centre of the circle is inside the rectangle
            if self.pointInside(otherShape.middlePoint):
                return True

            elif otherShape.collidesWithLine(
                (self.topLeft, Vector2(self.bottomRight.x, self.topLeft.y))):
                return True

            elif otherShape.collidesWithLine(
                    Vector2(self.bottomRight.x, self.topLeft.y),
                    self.bottomRight):
                return True

            elif otherShape.collidesWithLine(
                    self.bottomRight,
                    Vector2(self.topLeft.x, self.bottomRight.y)):
                return True

            elif otherShape.collidesWithLine(
                    Vector2(self.topLeft.x, self.bottomRight.y), self.topLeft):
                return True

            else:
                return False
예제 #15
0
파일: kick_ball.py 프로젝트: Mart100/Mork
 def get_angle_for_goal(agent, packet, ball_location):
     opponents_goal = get_opponents_goal(agent)
     ball_to_pole1 = Vector2(opponents_goal.x + 893 - ball_location.x,
                             opponents_goal.y - ball_location.y)
     ball_to_pole2 = Vector2(opponents_goal.x - 893 - ball_location.x,
                             opponents_goal.y - ball_location.y)
     #draw lines
     a = [ball_location.x, ball_location.y, 96]
     b = [
         ball_to_pole1.x + ball_location.x,
         ball_to_pole1.y + ball_location.y, 96
     ]
     c = [
         ball_to_pole2.x + ball_location.x,
         ball_to_pole2.y + ball_location.y, 96
     ]
     agent.renderer.draw_line_3d(a, b,
                                 agent.renderer.create_color(255, 0, 0, 0))
     agent.renderer.draw_line_3d(a, c,
                                 agent.renderer.create_color(255, 0, 0, 0))
     # return angle
     return abs(
         (ball_to_pole1.get_angle() - ball_to_pole2.get_angle()) / 2 * 1.5)
예제 #16
0
    def collidesWithLine(self, line):
        point1 = line[0]
        point2 = line[1]

        try:
            point1.id
            point2.id

        except AttributeError:
            point1 = Vector2(point1[0], point1[1])
            point2 = Vector2(point2[0], point2[1])

        #Point1 has to be 0 in order to turn the other point into a vector that we can use
        editedPoint = point2.subtract(point1)
        editedMiddle = self.middlePoint.subtract(point1)

        projection = editedMiddle.projection(editedPoint)
        newProjection = projection.add(point1)

        if self.pointInside(newProjection):
            return True
        else:
            return False
예제 #17
0
    def __init__(self, middlePoint, radius):
        self.id = "circle"

        #If the middlePoint is not provided as a vector, make it one
        try:
            middlePoint.id
            self.middlePoint = middlePoint

        except AttributeError:
            self.middlePoint = Vector2(middlePoint[0], middlePoint[1])

        self.x = self.middlePoint.x
        self.y = self.middlePoint.y

        self.radius = radius
예제 #18
0
파일: world.py 프로젝트: jcharra/StreetCatz
    def render(self, surface):
        display_x = min(
            self.dimension[0] - self.display_size[0],
            max(0, self.focussed_entity.location.x - self.display_size[0] / 2))
        display_y = min(
            self.dimension[1] - self.display_size[1],
            max(0, self.focussed_entity.location.y - self.display_size[1] / 2))
        surface.blit(
            self.background, (0, 0),
            (display_x, display_y, self.display_size[0], self.display_size[1]))

        for entity in self.entities.itervalues():
            if Vector2.get_distance(self.focussed_entity.location,
                                    entity.location) <= self.maximum_expansion:
                entity.render(surface, (display_x, display_y))

        if self.minimapVisible:
            minimapSize = (200, 100)
            minimapOffset = (10, 490)
            pygame.draw.rect(surface, (0, 0, 0),
                             pygame.Rect(minimapOffset, minimapSize))
            pygame.draw.rect(
                surface, (255, 255, 255),
                pygame.Rect((minimapOffset[0] - 1, minimapOffset[1] - 1),
                            (minimapSize[0] + 2, minimapSize[1] + 2)), 1)

            for entity in self.active_entities.itervalues():
                # render entity point on minimap
                x = minimapOffset[0] + int(
                    (minimapSize[0] * entity.location.x) / self.dimension[0])
                y = minimapOffset[1] + int(
                    (minimapSize[1] * entity.location.y) / self.dimension[1])
                if entity.name == 'player' and not entity.vehicle:
                    color = (0, 0, 255)
                    pygame.draw.circle(surface, color, (x, y), 3)
                elif entity.name == 'cat':
                    color = entity.hungerColour
                    pygame.draw.rect(surface, color, pygame.Rect((x, y),
                                                                 (2, 2)))
                elif entity.name == 'car':
                    color = (200, 200, 200)
                    pygame.draw.circle(surface, color, (x, y), 3)
예제 #19
0
파일: world.py 프로젝트: jcharra/StreetCatz
    def render(self, surface):
        display_x = min(
            self.dimension[0] - self.display_size[0], max(0, self.focussed_entity.location.x - self.display_size[0] / 2)
        )
        display_y = min(
            self.dimension[1] - self.display_size[1], max(0, self.focussed_entity.location.y - self.display_size[1] / 2)
        )
        surface.blit(self.background, (0, 0), (display_x, display_y, self.display_size[0], self.display_size[1]))

        for entity in self.entities.itervalues():
            if Vector2.get_distance(self.focussed_entity.location, entity.location) <= self.maximum_expansion:
                entity.render(surface, (display_x, display_y))

        if self.minimapVisible:
            minimapSize = (200, 100)
            minimapOffset = (10, 490)
            pygame.draw.rect(surface, (0, 0, 0), pygame.Rect(minimapOffset, minimapSize))
            pygame.draw.rect(
                surface,
                (255, 255, 255),
                pygame.Rect((minimapOffset[0] - 1, minimapOffset[1] - 1), (minimapSize[0] + 2, minimapSize[1] + 2)),
                1,
            )

            for entity in self.active_entities.itervalues():
                # render entity point on minimap
                x = minimapOffset[0] + int((minimapSize[0] * entity.location.x) / self.dimension[0])
                y = minimapOffset[1] + int((minimapSize[1] * entity.location.y) / self.dimension[1])
                if entity.name == "player" and not entity.vehicle:
                    color = (0, 0, 255)
                    pygame.draw.circle(surface, color, (x, y), 3)
                elif entity.name == "cat":
                    color = entity.hungerColour
                    pygame.draw.rect(surface, color, pygame.Rect((x, y), (2, 2)))
                elif entity.name == "car":
                    color = (200, 200, 200)
                    pygame.draw.circle(surface, color, (x, y), 3)
예제 #20
0
파일: kick_ball.py 프로젝트: Mart100/Mork
    def main(agent, packet):
        if kick_ball.ball_prediction != 0:
            ball_location = kick_ball.ball_prediction.pos
        else:
            ball_location = Vector3(packet.game_ball.physics.location)
            kick_ball.prediction_timer = -1
        ball = agent.ball
        car = agent.car
        car_location = car.pos.to_2d()
        car_to_ball_vector = Vector3(ball.pos) - Vector3(car.pos)
        car_to_ball_magnitude = car_to_ball_vector.magnitude()
        car_to_ball_magnitude_2d = car_to_ball_vector.to_2d().magnitude()
        car_direction = get_car_facing_vector(car)
        goal = get_opponents_goal(agent)
        go_to = car_location
        plus = 0

        # ball prediction
        kick_ball.prediction_timer -= 1 / 60
        if kick_ball.prediction_timer < -0.1:
            agent.car_status = 'none'
            kick_ball.in_position = False
            time = kick_ball.predict_when_ball_hit(agent)
            kick_ball.prediction_timer = time
            kick_ball.ball_prediction = ball.prediction[int(time * 60)]
        kick_ball.correction_timer = kick_ball.when_ball_hit_correction(agent)
        kick_ball.ball_prediction = ball.prediction[int(
            cap_num(kick_ball.prediction_timer * 60, 0, 1e9))]

        # a few variables
        ball_location = kick_ball.ball_prediction.pos
        car_to_ball_vector = Vector3(ball.pos) - Vector3(car.pos)
        car_to_ball_magnitude = car_to_ball_vector.magnitude()
        car_to_ball_magnitude_2d = car_to_ball_vector.to_2d().magnitude()
        ideal_car_location = kick_ball.get_ideal_car_location(
            agent, packet, ball_location)

        # draw line from ball to ideal car location
        Vector3(ball_location).draw_to(agent, ideal_car_location, [0, 100, 0])

        # 3D correction timer vs actual prediction
        agent.renderer.draw_string_3d(
            car.pos.change('z', 100).get_array(), 2, 2, 'corr: ' + str(
                round(kick_ball.correction_timer, 2) -
                round(kick_ball.prediction_timer, 2)), white(agent))

        # draw place where car will hit ball
        agent.renderer.draw_string_3d(ball_location.get_array(), 2, 2,
                                      ball_location.string(), white(agent))

        ideal_car_to_ball_angle = (ball_location -
                                   ideal_car_location).to_2d().get_angle()
        car_to_ball_to_angle = (ball_location - car.pos).to_2d().get_angle()
        difference_angle_car_ideal = difference_angles(ideal_car_to_ball_angle,
                                                       car_to_ball_to_angle)
        if difference_angle_car_ideal > kick_ball.get_angle_for_goal(
                agent, packet, ball_location) * 2:
            kick_ball.in_position = False
        car_inline_bool = abs(
            difference_angle_car_ideal) < kick_ball.get_angle_for_goal(
                agent, packet, ball_location) * 2
        # If car not close enough to ideal and car not close to idealLine. Go there
        if Vector2(
                ideal_car_location.x - car_location.x,
                ideal_car_location.y - car_location.y).magnitude(
                ) > 1000 and not car_inline_bool and not kick_ball.in_position:
            go_to = ideal_car_location
            #plus = -difference_angle_car_ideal/(car_to_ball_magnitude/200)
            # double jump if on ground and straight and going good direction and far away
            far_away_enough = Vector2(
                car_location.x - ideal_car_location.x,
                car_location.y - ideal_car_location.y).magnitude() > 1000
            # draw ideal location
            a = [ideal_car_location.x, ideal_car_location.y, 17]
            agent.renderer.draw_rect_3d(a, 40, 40, True,
                                        own_color(agent, packet))
        # Else head towards the ball
        else:
            kick_ball.in_position = True
            # predict ball location and go there
            go_to = ball_location

            plus = -difference_angle_car_ideal / (car_to_ball_magnitude / 200)
            #if car_to_ball_magnitude_2d > 2000: plus = -difference_angle_car_ideal/40
            # boost
            too_slow = kick_ball.correction_timer > kick_ball.prediction_timer + 0.01
            if car.pos.z < 17.1 and car_inline_bool and too_slow:
                agent.controller_state.boost = True
            agent.renderer.draw_line_3d(
                car.pos.get_array(), ball_location.get_array(),
                agent.renderer.create_color(255, 255, 255, 255))
            agent.renderer.draw_line_3d(ideal_car_location.get_array(),
                                        ball_location.get_array(),
                                        own_color(agent, packet))

        draw_text(agent, 'LR. corr: ' + str(plus), 110)
        aim_to(agent, go_to, plus)

        # If realy close to ball and good direction Jump
        if car_to_ball_magnitude < 200 and abs(
                car_direction.correction_to(
                    Vector2(ball_location.x, ball_location.y) -
                    car_location)) < 0.1:
            double_jump(agent)

        agent.controller_state.throttle = 1
        if kick_ball.correction_timer + 0.05 < kick_ball.prediction_timer:
            agent.controller_state.throttle = 1 - (
                kick_ball.prediction_timer - kick_ball.correction_timer -
                kick_ball.prediction_timer) / 5
        # if me hit the ball stop kicking the ball
        if packet.game_ball.latest_touch.player_name == car.name and packet.game_info.seconds_elapsed - packet.game_ball.latest_touch.time_seconds < 1:
            agent.car_status = 'none'
            kick_ball.ball_prediction = 0
        return agent
예제 #21
0
 def dropFood(self):
     if self.foodAmount <= 0 or self.vehicle:
         return None
     else:
         self.foodAmount -= 1
         return Food(self.location - Vector2(10,0))
예제 #22
0
파일: main.py 프로젝트: jcharra/StreetCatz
def runLevel(screen, level_number, cat_number):
    soundChannel = pygame.mixer.Channel(0)
    finishSound = pygame.mixer.Sound('../sounds/finish.ogg')

    builder = LevelBuilder()
    level = builder.buildLevelFromFile('../levels/level%s.txt' % level_number)
    world = World(SCREEN_SIZE, level)

    car = Car(Vector2(100, 100))
    player = Player(Vector2(100, 180))

    world.add_entity(player)
    world.add_entity(car)
    world.setFocus(player)

    worldobserver = WorldObserver(world)
    clock = pygame.time.Clock()

    for i in range(cat_number):
        cat = Cat(
            Vector2(randint(0, world.dimension[0]),
                    randint(0, world.dimension[1])), world)
        world.add_entity(cat)

    countdown_to_next_level = LEVEL_INTERMEDIATE_TIME
    while True:

        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
            if event.type == KEYDOWN:
                if event.key == K_LEFT:
                    player.move(LEFT)
                elif event.key == K_RIGHT:
                    player.move(RIGHT)
                elif event.key == K_UP:
                    player.move(UP)
                elif event.key == K_DOWN:
                    player.move(DOWN)
                elif event.key == K_SPACE:
                    food = player.dropFood()
                    if food is not None:
                        world.add_entity(food)
                elif event.key == K_c:
                    player.switchVehicle(car)
                    world.setFocus(player.vehicle or player)
                elif event.key == K_m:
                    world.toggleMinimap()

        time_passed = clock.tick(30)

        world.process(time_passed)
        world.render(screen)
        worldobserver.writeMessages(screen)

        if worldobserver.levelFinished:
            if countdown_to_next_level == LEVEL_INTERMEDIATE_TIME:
                soundChannel.play(finishSound)
            countdown_to_next_level -= 2
            if countdown_to_next_level <= 0:
                return

            for r in range(countdown_to_next_level + 1,
                           LEVEL_INTERMEDIATE_TIME, 8):
                pygame.draw.circle(screen, (0, 0, 0),
                                   (SCREEN_SIZE[0] / 2, SCREEN_SIZE[1] / 2), r,
                                   1)

        pygame.display.update()
예제 #23
0
파일: cat.py 프로젝트: jcharra/StreetCatz
 def findRandomTarget(self):
     self.cat.destination = self.cat.location + Vector2(randint(-200, 200), randint(-200, 200))
예제 #24
0
파일: cat.py 프로젝트: jcharra/StreetCatz
 def entry_actions(self):
     self.cat.set_image(self.cat.roamingImage, 4)
     self.cat.speed = 100
     self.cat.animationSpeed = 0.1
     self.cat.destination = self.cat.pot.location - Vector2(30, 0)
예제 #25
0
파일: cat.py 프로젝트: jcharra/StreetCatz
 def check_conditions(self):
     if self.cat.pot is not None and Vector2.get_distance(self.cat.location, self.cat.destination) < 10:
         return "eating"
     return None
예제 #26
0
from vectors import (Vector2, Vector3)


class Line:
    def __init__(self, start, end):
        if not (isinstance(start, (Vector2, Vector3)) and isinstance(
                end, (Vector2, Vector3)) and type(start) == type(end)):
            raise TypeError(
                "Both the start and end points of the line need to be a Vector2 or Vector3 (Start and end need to match type)"
            )
        self.start = start
        self.end = end

    def length(self):
        return (self.end - self.start).magnitude()


if __name__ == "__main__":
    print(Line(Vector2(0, 0), Vector2(3, 4)).length())