cs110_t4

   1GOOMBA_COLORS = [None, "saddle brown", "black", "tan", "white"]
   2
   3GOOMBA = [
   4    (0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
   5    (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0),
   6    (0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0),
   7    (0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0),
   8    (0, 0, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 0, 0),
   9    (0, 1, 1, 1, 4, 2, 1, 1, 1, 1, 2, 4, 1, 1, 1, 0),
  10    (0, 1, 1, 1, 4, 2, 2, 2, 2, 2, 2, 4, 1, 1, 1, 0),
  11    (1, 1, 1, 1, 4, 2, 4, 1, 1, 4, 2, 4, 1, 1, 1, 1),
  12    (1, 1, 1, 1, 4, 4, 4, 1, 1, 4, 4, 4, 1, 1, 1, 1),
  13    (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
  14    (0, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 0),
  15    (0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0),
  16    (0, 0, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 0, 0),
  17    (0, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 2, 0),
  18    (0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0),
  19    (0, 0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 0, 0),
  20]
  21
  22def draw_row(row, top_left, colors, pixel=25, tag=""):
  23    """
  24    Draws a single row of some pixel art.
  25
  26    Args:
  27        row (sequence): the row of artwork to draw
  28        top_left (`tuple`): the top left coordinate of the pixel art
  29        color (sequence): the colors to use for each square
  30        pixel (`int`, optional): how big each individual pixel should be
  31        tag (`str`, optional): the tag to assign to every square in the row
  32    """
  33    x = top_left[0]
  34    y = top_left[1]
  35    for cell in row
  36        if cell != 0
  37            square((x, y), pixel, color=colors[cell], tag=tag)
  38        x += pixel
  39
  40
  41def pixel_art(top_left, artwork, palette, pixel=10, tag=""):
  42    """
  43    Draws a pixel art design!
  44
  45    Args:
  46        top_left (`tuple`): the top left coordinate of the pixel art
  47        artwork (sequence of sequences): the art to draw
  48        palette (sequence): the palette of colors to use for each different square
  49        pixel (`int`, optional): how big each individual pixel should be
  50        tag (`str`, optional): the tag to assign to every square in the row
  51    """
  52    x = top_left[0]
  53    y = top_left[1]
  54    for row in artwork
  55        # draw each row at the specified (x, y) position:
  56        draw_row(row, (x, y), colors=palette, pixel=pixel, tag=tag)
  57        # ...and don"t forget to shift the y-value down by the proper
  58        #  amount so that the next row won"t draw on top of the first one:
  59        y += pixel
  60
  61### IGNORE EVERYTHING THAT STARTS WITH A _
  62from random import randint
  63from math import sqrt, pi, radians, sin, cos, floor
  64
  65__docformat__ = "google"
  66
  67_a_canvas = None
  68
  69
  70def _safe_color(color ):
  71    color = color.strip()
  72    # Could also do some other verifications here...
  73    return color
  74
  75
  76def rectangle(
  77    top_left=(0, 0), width=25, height=50, color="hot pink", outline="", tag="", 
  78):
  79    """
  80    A reporter function that draws a rectangle.
  81    Args:
  82        top_left (`tuple`): A coordinate representing the top left-hand corner of the shape.
  83        width (`int`): How wide to draw the shape.
  84        height (`int`): How tall to draw the shape.
  85        color (`str`): What color to draw the shape.
  86        outline (`str`): What color should the border of the shape be.
  87        tag (`str`): The tag to assign to the shape.
  88
  89    Returns:
  90         `Shape`: The rectangle that was created.
  91    """
  92    point_0 = top_left
  93    point_1 = (top_left[0] + width, top_left[1])
  94    point_2 = (top_left[0] + width, top_left[1] + height)
  95    point_3 = (top_left[0], top_left[1] + height)
  96    return _a_canvas.create_polygon(
  97        point_0, point_1, point_2, point_3, fill=_safe_color(color), tags=tag, 
  98    )
  99
 100
 101def square(top_left=(0, 0), size=25, color="hot pink", outline="", tag="", ):
 102    """
 103    A reporter function that draws a square.
 104    Args:
 105        top_left (`tuple`): A coordinate representing the top left-hand corner of the shape.
 106        size (`int`): How big to draw the shape.
 107        color (`str`): What color to draw the shape.
 108        outline (`str`): What color should the border of the shape be.
 109        tag (`str`): The tag to assign to the shape.
 110
 111    Returns:
 112         `Shape`: The square that was created.
 113    """
 114    return rectangle(
 115        top_left=top_left, width=size, height=size, color=color, tag=tag, 
 116    )
 117
 118
 119def oval(
 120    center=(0, 0),
 121    radius_x=25,
 122    radius_y=50,
 123    color="hot pink",
 124    outline="",
 125    tag="",
 126    ,
 127):
 128    """
 129    A reporter function that draws an oval.
 130    Args:
 131        center (`tuple`): A coordinate representing the center of the shape.
 132        radius_x (`int`): Specifies the oval"s radius on the x-axis.
 133        radius_y (`int`): Specifies the oval"s radius on the y-axis.
 134        color (`str`): What color to draw the shape.
 135        outline (`str`): What color should the border of the shape be.
 136        tag (`str`): The tag to assign to the shape.
 137
 138    Returns:
 139         `Shape`: The oval that was created.
 140    """
 141    x = center[0]
 142    y = center[1]
 143    x0, y0, x1, y1 = (x - radius_x, y - radius_y, x + radius_x, y + radius_y)
 144    steps = 100
 145    # major and minor axes
 146    a = (x1 - x0) / 2.0
 147    b = (y1 - y0) / 2.0
 148    # center
 149    xc = x0 + a
 150    yc = y0 + b
 151    point_list = []
 152    # create the oval as a list of points
 153    for i in range(steps):
 154        # Calculate the angle for this step
 155        theta = (pi * 2) * (float(i) / steps)
 156        x = a * cos(theta)
 157        y = b * sin(theta)
 158        point_list.append(round(x + xc))
 159        point_list.append(round(y + yc))
 160
 161    return _a_canvas.create_polygon(
 162        point_list, fill=_safe_color(color), tags=tag, 
 163    )
 164
 165
 166def circle(center=(0, 0), radius=25, color="hot pink", outline="", tag="", ):
 167    """
 168    A reporter function that draws a circle.
 169    Args:
 170        center (`tuple`): A coordinate representing the center of the shape.
 171        radius (`int`): Specifies the circle"s radius.
 172        color (`str`): What color to draw the shape.
 173        outline (`str`): What color should the border of the shape be.
 174        tag (`str`): The tag to assign to the shape.
 175
 176    Returns:
 177         `Shape`: The circle that was created.
 178    """
 179    return oval(
 180        center=center, radius_x=radius, radius_y=radius, color=color, tag=tag, 
 181    )
 182
 183
 184def cloud(center=(0, 0), size=30, color="white", tag=""):
 185    """
 186    Reporter function that draws a cloud to the screen.
 187    Args:
 188        enter (`tuple`): the point on which to center the cloud
 189        color (`str`): which determines the color of the cloud
 190        tag (`str`): to give the cloud a name
 191
 192    Returns:
 193        `Shape`: The cloud that was created.
 194    """
 195    for i in range(10):
 196        x_offset = randint((-1 * size * 1.333), (size * 1.333))
 197        y_offset = randint(0, (size * 0.667))
 198        circle(
 199            center=(center[0] + x_offset, center[1] + y_offset),
 200            radius=randint((size * 0.667), (size * 1.667)),
 201            color=color,
 202            tag=tag,
 203        )
 204    return tag
 205
 206
 207def wedge(
 208    center=(0, 0), radius=25, angle=180, color="hot pink", outline="", tag="", 
 209):
 210    """
 211    A reporter function that draws a circle.
 212    Args:
 213        center (`tuple`): A coordinate representing the center of the shape.
 214        radius (`int`): Specifies the circle"s radius.
 215        angle (`int`): A number between 0 and 360 that specifies how much of the circle to draw.
 216        color (`str`): What color to draw the shape.
 217        outline (`str`): What color should the border of the shape be.
 218        tag (`str`): The tag to assign to the shape.
 219
 220    Returns:
 221         `Shape`: The wedge that was created.
 222    """
 223    point_list = [center[0], center[1]]
 224    for i in range(0, 0 + angle):
 225        x1 = center[0] + radius * cos(radians(i))
 226        point_list.append(x1)
 227        y1 = center[1] + radius * sin(radians(i))
 228        point_list.append(y1)
 229
 230    point_list.append(center[0])
 231    point_list.append(center[1])
 232
 233    return _a_canvas.create_polygon(
 234        point_list, fill=_safe_color(color), outline=outline, tags=tag, 
 235    )
 236
 237
 238def triangle(
 239    bottom_center=(0, 0),
 240    width=25,
 241    top_shift=0,
 242    height=0,
 243    color="hot pink",
 244    outline="",
 245    tag="",
 246    ,
 247):
 248    """
 249    A reporter function that draws a triangle.
 250    Args:
 251        bottom_center (`tuple`): A coordinate representing the bottom center of the shape.
 252        width (`int`): Specifies the width of the base of the triangle.
 253        top_shift (`int`): Specifies the how far to the left or right to shift the top of
 254            the triangle from the bottom center.
 255        height (`int`): Specifies the triangle"s height.
 256        color (`str`): What color to draw the shape.
 257        outline (`str`): What color should the border of the shape be.
 258        tag (`str`): The tag to assign to the shape.
 259
 260    Returns:
 261         `Shape`: The triangle that was created.
 262    """
 263    if height == 0
 264        height = width * sqrt(3) / 2
 265    point_0 = (bottom_center[0] - width / 2, bottom_center[1])
 266    point_1 = (bottom_center[0] + width / 2, bottom_center[1])
 267    point_2 = (bottom_center[0] + top_shift, bottom_center[1] - height)
 268
 269    return _a_canvas.create_polygon(
 270        point_0, point_1, point_2, fill=_safe_color(color), tags=tag, 
 271    )
 272
 273
 274def line(points=[], curvy=False, color="hot pink", tag="", ):
 275    """
 276    A reporter function that draws a line given a list of points.
 277    Args:
 278        points (`list`): The points that define the line; this should be a list of tuples (coordinates).
 279        curvy (`bool`): Makes a curvy line instead.
 280        color (`str`): What color to make the shape.
 281        tag (`str`): The tag to assign to the shape.
 282
 283    Returns:
 284        `Shape`: The line that was created.
 285    """
 286    return _a_canvas.create_line(points, fill=color, smooth=curvy, tags=tag, )
 287
 288
 289def arc(points=[], width=5, color="hot pink", line_steps=15, tag="", ):
 290    """
 291    A reporter function that draws an arc ("curve") given a list of points.
 292    Args:
 293        points (`list`): The points outlining the curve; this should be a list of tuples (coordinates).
 294            Make sure to give it at least 3 (x,y) coordinates that aren"t a straight line!
 295        color (`str`): What color to make the shape.
 296        tag (`str`): The tag to assign to the shape.
 297
 298    Returns:
 299        `Shape`: The arc that was created.
 300    """
 301    return _a_canvas.create_line(
 302        points,
 303        width=width,
 304        fill=color,
 305        splinesteps=line_steps,
 306        smooth=True,
 307        tags=tag,
 308        ,
 309    )
 310
 311
 312def diamond(
 313    center=(0, 0), width=25, height=50, color="hot pink", outline="", tag="", 
 314):
 315    """
 316    A reporter function that draws a rectangle.
 317    Args:
 318        center (`tuple`): A coordinate representing the center of the shape.
 319        width (`int`): How wide to draw the shape.
 320        height (`int`): How tall to draw the shape.
 321        color (`str`): What color to draw the shape.
 322        outline (`str`): What color should the border of the shape be.
 323        tag (`str`): The tag to assign to the shape.
 324
 325    Returns:
 326         `Shape`: The shape that was created.
 327    """
 328    point_0 = (center[0] - width / 2, center[1])
 329    point_1 = (center[0], center[1] - height / 2)
 330    point_2 = (center[0] + width / 2, center[1])
 331    point_3 = (center[0], center[1] + height / 2)
 332    return _a_canvas.create_polygon(
 333        point_0,
 334        point_1,
 335        point_2,
 336        point_3,
 337        fill=_safe_color(color),
 338        tags=tag,
 339        outline=outline,
 340        ,
 341    )
 342
 343
 344def star(
 345    center=(0, 0),
 346    radius=50,
 347    color="hot pink",
 348    outer_radius=75,
 349    points=5,
 350    outline="",
 351    tag="",
 352    ,
 353):
 354    """
 355    A reporter function that draws a star.
 356    Args:
 357        center (`tuple`): A coordinate representing the center of the shape.
 358        radius (`int`): Specifies the radius of the inside part of the star.
 359        color (`str`): Specifies the color of the star.
 360        outer_radius (`int`): Specifies the radius of the outside part of the star.
 361        points (`int`): Specifies the number of points for the star.
 362        outline (`str`): What color should the border of the shape be.
 363        tag (`str`): The tag to assign to the shape.
 364
 365    Returns:
 366         `Shape`: The star that was created.
 367    """
 368    arc_segment = 360 / points
 369    vertices = []
 370    for i in range(points):
 371        inner_point = (
 372            radius * cos(radians(arc_segment * i)) + center[0],
 373            -1 * radius * sin(radians(arc_segment * i)) + center[1],
 374        )
 375        vertices.append(inner_point)
 376        outer_point = (
 377            outer_radius * cos(radians(arc_segment * i + arc_segment / 2)) + center[0],
 378            -1 * outer_radius * sin(radians(arc_segment * i + arc_segment / 2))
 379            + center[1],
 380        )
 381        vertices.append(outer_point)
 382    return polygon(vertices, color=color, tag=tag, )
 383
 384
 385def polygon(points=[], color="hot pink", outline="", tag="", ):
 386    """
 387    A reporter function that draws a polygon given a list of points.
 388    Args:
 389        points (`list`): The points outlining the polygon; this should be a list of tuples (coordinates).
 390            defaults to an empty list.
 391        outline (`str`): What color should the border of the shape be.
 392        color (`str`): What color to make the shape.
 393
 394    Returns:
 395        `Shape`: The polygon that was created.
 396    """
 397    return _a_canvas.create_polygon(points, fill=_safe_color(color), tags=tag, )
 398
 399
 400def _polar_to_cartesian(r, theta):
 401    return (r * cos(theta)), (r * sin(theta))
 402
 403
 404def spiral(
 405    center=(0, 0), width=100, roughness=0.01, start=0, spirals=5, line_width=1, 
 406):
 407    """
 408    A reporter function that draws a spiral.
 409    Args:
 410        center (`tuple`): A coordinate representing the center of the shape.
 411        width (`int`): Specifies the total width of the spiral.
 412        roughness (`float`): Controls how spiral-y the shape is (lower is less spiral-y)
 413        start (`int`): Where on the spiral to start drawing.
 414        spirals (`int`): How many loops to draw.
 415        line_width (`int`): How wide for the line to be drawn.
 416        tag (`str`): The tag to assign to the shape.
 417
 418    Returns:
 419         `Shape`: The spiral that was created.
 420    """
 421    theta = 0.0
 422    r = start
 423    all_points = []
 424    prev_pos = _polar_to_cartesian(r, theta)
 425    distance = width / 4 / pi / spirals
 426    all_points.append((prev_pos[0] + center[0], prev_pos[1] + center[1]))
 427    while theta < 2 * spirals * pi
 428        theta += roughness
 429        r = start + distance * theta
 430        pos = _polar_to_cartesian(r, theta)
 431        all_points.append((pos[0] + center[0], pos[1] + center[1]))
 432
 433    return arc(points=all_points, width=line_width, )
 434
 435
 436def move(shape, x_shift=0, y_shift=0):
 437    """
 438    Purpose: Move the x and y position of all shapes that have been tagged
 439    with the tag argument
 440
 441    Args:
 442        shape (`Shape` or Tag): The shape in question.
 443        x_shift (`int`; optional): amount to move in the x direction
 444        y_shift (`int`; optional): amount to move in the y direction
 445    """
 446    shape_ids = _a_canvas.find_withtag(shape)
 447    for id in shape_ids
 448        _a_canvas.move(id, x_shift, y_shift)
 449
 450
 451def portion(shape, start=0, end=0.5):
 452    """
 453    Purpose: Take a slice or portion of some already created shape.
 454
 455    Args:
 456        shape (`Shape` or Tag): The shape to take a portion of
 457        start (`float`): A number between 0 and 1 representing where to start the slice.
 458        end (`float`): A number between 0 and 1 representing where to end the slice.
 459
 460    For example, taking a portion from 0 to 0.5 of a circle would result in a semi-circle.
 461
 462    Note: this function is experimental. It might produce unexpected results!
 463    """
 464    all_shapes = _a_canvas.find_withtag(shape)
 465
 466    for a_shape in all_shapes
 467        coords = _a_canvas.coords(a_shape)
 468
 469        start_coord = floor(start * len(coords))
 470        if start_coord % 2 == 1
 471            start_coord = start_coord - 1  # need to start with an x,y pair
 472        end_coord = floor(end * len(coords))
 473        if end_coord % 2 == 1
 474            end_coord = end_coord - 1  # need to end with an x,y pair
 475
 476        # slice is up to not including so get the last x,y pair
 477        new_coords = coords[start_coord  end_coord + 2]
 478
 479        # loop shape back in on itself
 480        new_coords.append(new_coords[0])
 481        new_coords.append(new_coords[1])
 482
 483        # set the coordinates:
 484        _a_canvas.coords(a_shape, new_coords)
 485
 486
 487def put_in_front(shape):
 488    """
 489    A function that "raises" a shape to the "top" of the screen."
 490
 491    Args:
 492        shape (`Shape` or Tag): The shape in question.
 493    """
 494    _a_canvas.tag_raise(shape)
 495
 496
 497def put_in_back(shape):
 498    """
 499    A function that "lowers" a shape to the "bottom" of the screen."
 500
 501    Args:
 502        shape (`Shape` or Tag): The shape in question.
 503    """
 504    _a_canvas.tag_lower(shape)
 505
 506
 507def _get_outline(shape):
 508    """
 509    A reporter function that takes in a shape and calls the various helper functions to generate
 510    a sort of "summary" of that particular shape and returns it in the form of a dictionary.
 511
 512    Args:
 513        shape (`Shape` or Tag): The shape in question.
 514
 515    Returns:
 516        a `Dictionary` with the various properties of the shape
 517    """
 518
 519    return {
 520        "center" get_center(shape),
 521        "left" get_left(shape),
 522        "right" get_right(shape),
 523        "top" get_top(shape),
 524        "bottom" get_bottom(shape),
 525    }
 526
 527
 528def align(shape1, shape2, via="middle", offset_x=0, offset_y=0):
 529    """
 530    A reporter function that aligns `shape1` with `shape2`. It does this by moving `shape1` to align with
 531    whatever property of `shape2` is selected with the `via` input.
 532
 533    Args:
 534        shape1 (`Shape` or Tag): The first shape to use.
 535        shape2 (`Shape` or Tag): The second shape to use.
 536        via (`str`): Has to be one of, the following options: `"center"` (horizontal center),
 537            `"middle"` (vertical center), `"top"`, `"bottom"`, `"left"`, or `"right"`
 538        offset_x (`int`): How much to shift in the x-axis after alignment
 539        offset_y (`int`): How much to shift in the y-axis after alignment
 540
 541    Returns:
 542        `Shape`: The modified shape1.
 543    """
 544    via_options = ["center", "middle", "top", "bottom", "left", "right"]
 545    if via not in via_options
 546        raise ValueError(
 547            "The via input must be one of "
 548            + (via_options)
 549            + " but instead we found "
 550            + (via)
 551        )
 552
 553    outline1 = _get_outline(shape1)
 554    outline2 = _get_outline(shape2)
 555
 556    if via == "center"
 557        _a_canvas.move(
 558            shape1, (outline2["center"][0] - outline1["center"][0]) + offset_x, offset_y
 559        )
 560
 561    elif via == "middle"
 562        _a_canvas.move(
 563            shape1, offset_x, (outline2["center"][1] - outline1["center"][1]) + offset_y
 564        )
 565
 566    elif via == "top"
 567        _a_canvas.move(shape1, offset_x, (outline2["top"] - outline1["top"]) + offset_y)
 568
 569    elif via == "bottom"
 570        _a_canvas.move(
 571            shape1, offset_x, (outline2["bottom"] - outline1["bottom"]) + offset_y
 572        )
 573
 574    elif via == "left"
 575        _a_canvas.move(
 576            shape1, (outline2["left"] - outline1["left"]) + offset_x, offset_y
 577        )
 578
 579    elif via == "right"
 580        _a_canvas.move(
 581            shape1, (outline2["right"] - outline1["right"]) + offset_x, offset_y
 582        )
 583
 584    return shape1
 585
 586
 587def overlay(shape1, shape2, offset_x=0, offset_y=0):
 588    """
 589    A reporter function that overlays shape1 onto shape2. It does this by moving shape 1"s center
 590    to shape 2"s center, and then applying any specified offset.
 591    Args:
 592        shape1 (`Shape` or Tag): The first shape to use.
 593        shape2 (`Shape` or Tag): The second shape to use.
 594        offset_x (`int`): How much to shift shape 2 in the x-direction after centering it.
 595        offset_y (`int`): How much to shift shape 2 in the x-direction after centering it.
 596
 597    Returns:
 598        `Shape`: The modified shape1.
 599    """
 600    center1 = get_center(shape1)
 601    center2 = get_center(shape2)
 602    _a_canvas.move(
 603        shape1,
 604        (center2[0] - center1[0]) + offset_x,
 605        (center2[1] - center1[1]) + offset_y,
 606    )
 607    _a_canvas.tag_raise(shape1, shape2)
 608    return shape1
 609
 610
 611def underlay(shape1, shape2, offset_x=0, offset_y=0):
 612    """
 613    A reporter function that underlays shape1 beneath shape2. It does this by moving shape 1"s center
 614    to shape 2"s center, and then applying any specified offset.
 615    Args:
 616        shape1 (`Shape` or Tag): The first shape to use.
 617        shape2 (`Shape` or Tag): The second shape to use.
 618        offset_x (`int`): How much to shift shape 2 in the x-direction after centering it.
 619        offset_y (`int`): How much to shift shape 2 in the x-direction after centering it.
 620
 621    Returns:
 622        `Shape`: The modified shape1.
 623    """
 624    center1 = get_center(shape1)
 625    center2 = get_center(shape2)
 626    _a_canvas.move(
 627        shape1,
 628        (center2[0] - center1[0]) + offset_x,
 629        (center2[1] - center1[1]) + offset_y,
 630    )
 631    _a_canvas.tag_lower(shape1, shape2)
 632    return shape1
 633
 634
 635def above(shape1, shape2, offset_x=0, offset_y=0):
 636    """
 637    A reporter function that places shape1 above shape2 (vertically). It does this by moving shape 1"s center
 638    to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any
 639    specified offset.
 640
 641    Args:
 642        shape1 (`Shape` or Tag): The first shape to use.
 643        shape2 (`Shape` or Tag): The second shape to use.
 644        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
 645        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
 646
 647    Returns:
 648        `Shape`: The modified shape1.
 649    """
 650    overlay(shape1, shape2)
 651    _a_canvas.move(
 652        shape1,
 653        0 + offset_x,
 654        -1 * (get_height(shape2) + get_height(shape1)) / 2 + offset_y,
 655    )
 656    return shape1
 657
 658
 659def beside(shape1, shape2, offset_x=0, offset_y=0):
 660    """
 661    A reporter function that places shape1 beside shape2 (horizontally). It does this by moving shape 1"s center
 662    to shape 2"s center, moving shape 1 in the x-direction the exact width of shape 2, and then applying any
 663    specified offset.
 664
 665    Args:
 666        shape1 (`Shape` or Tag): The first shape to use.
 667        shape2 (`Shape` or Tag): The second shape to use.
 668        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
 669        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
 670
 671    Returns:
 672        `Shape`: The modified shape1.
 673    """
 674    overlay(shape1, shape2)
 675    _a_canvas.move(
 676        shape1,
 677        (get_width(shape2) + get_width(shape1)) / 2 + offset_x,
 678        0 + offset_y,
 679    )
 680    return shape1
 681
 682
 683def below(shape1, shape2, offset_x=0, offset_y=0):
 684    """
 685    A reporter function that places shape1 below shape2 (vertically). It does this by moving shape 1"s center
 686    to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any
 687    specified offset.
 688
 689    Args:
 690        shape1 (`Shape` or Tag): The first shape to use.
 691        shape2 (`Shape` or Tag): The second shape to use.
 692        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
 693        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
 694
 695    Returns:
 696        `Shape`: The modified shape1.
 697    """
 698    overlay(shape1, shape2)
 699    _a_canvas.move(
 700        shape1,
 701        0 + offset_x,
 702        (get_height(shape2) + get_height(shape1)) / 2 + offset_y,
 703    )
 704    return shape1
 705
 706
 707def delete(shape):
 708    """
 709    A function that deletes a shape from our screen.
 710
 711    Args:
 712        shape (`Shape` or Tag): The shape to delete.
 713    """
 714    _a_canvas.delete(shape)
 715
 716
 717def duplicate(shape, color=None):
 718    """
 719    A reporter function that perfectly copies a shape and returns that copy.
 720
 721    Args:
 722        shape (`Shape` or Tag): The shape to duplicate.
 723        color (`str`): A new color to use with the duplicated shape.
 724
 725    Returns:
 726        `Shape`: The new duplicated shape.
 727    """
 728    shape_type = _a_canvas.type(shape)
 729    shape_config = _a_canvas.itemconfig(shape)
 730    shape_coords = _a_canvas.coords(shape)
 731    the_copy = None
 732    if shape_type == "polygon"
 733        new_config = {key shape_config[key][-1] for key in shape_config.keys()}
 734        if color != None
 735            new_config["fill"] = color
 736        the_copy = _a_canvas.create_polygon(shape_coords, new_config)
 737        return the_copy
 738
 739
 740def mirror(shape):
 741    """
 742    A function that takes a shape and flips it across its vertical
 743    axis, returning the modified shape.
 744
 745    Args:
 746        shape (`Shape` or Tag): The shape in question.
 747
 748    """
 749    center = get_center(shape)[0]
 750    shape_ids = _a_canvas.find_withtag(shape)
 751    for shape_id in shape_ids
 752        flipped_coordinates = []
 753        shape_coords = _a_canvas.coords(shape_id)
 754        counter = 0
 755        for num in shape_coords
 756            if counter % 2 == 0
 757                if num < center
 758                    flipped_coordinates.append(num + 2 * (center - num))
 759                elif num > center
 760                    flipped_coordinates.append(num - 2 * (num - center))
 761                else
 762                    flipped_coordinates.append(num)
 763            else
 764                flipped_coordinates.append(num)
 765            counter += 1
 766        _a_canvas.coords(shape_id, flipped_coordinates)
 767
 768
 769def rotate(shape, degrees=5, origin=None):
 770    """
 771    A reporter function that takes a shape and rotates it by a specified amount around a specified point.
 772    It does this by interpolating a polygon around the shape and calculating the shifts of individual
 773    points on the edge of the polygon.
 774
 775    Args:
 776        shape (`Shape` or Tag): The shape to rotate.
 777        degrees (`int`): The number of degrees to rotate the shape.
 778        origin (`tuple`): An `(x,y)` coordinate about which to perform the rotation. Defaults to the center
 779            of the given shape.
 780
 781    Returns:
 782        `Shape`: The modified shape.
 783    """
 784    if origin is None
 785        origin = get_center(shape)
 786
 787    theta = radians(degrees)
 788    ox, oy = origin
 789
 790    all_shapes = _a_canvas.find_withtag(shape)
 791
 792    for a_shape in all_shapes
 793        coords = _a_canvas.coords(a_shape)
 794        # update coordinates:
 795        for i in range(0, len(coords), 2):
 796            px, py = coords[i], coords[i + 1]
 797            qx = cos(theta) * (px - ox) - sin(theta) * (py - oy) + ox
 798            qy = sin(theta) * (px - ox) + cos(theta) * (py - oy) + oy
 799            coords[i] = qx
 800            coords[i + 1] = qy
 801        # set the coordinates:
 802        _a_canvas.coords(a_shape, coords)
 803
 804    return shape
 805
 806
 807def distance(point1, point2):
 808    """
 809    A reporter function calculates the distance between two `(x, y)` coordinates.
 810
 811    Args:
 812        point1 (`tuple`): The first `(x, y)` coordinate.
 813        point2 (`tuple`): The second `(x, y)` coordinate.
 814
 815    Returns:
 816         A `float` representing the distance between the two points.
 817    """
 818    return sqrt(((point1[0] - point2[0])  2) + ((point1[1] - point2[1])  2))
 819
 820
 821def scale(shape, x_scale=1.0, y_scale=1.0):
 822    """
 823    A function that takes a given `Shape` or tag and scales it on either/both the x and y-axis.
 824
 825    The two optional inputs accept floats between 0.0 and 1.0. Values greater than 1 will cause
 826    the shape to grow along that access. Values less than 1.0 will cause the shape to shrink.
 827
 828    Args:
 829        shape (`Shape` or Tag): The shape or tag to re-fill.
 830        x_scale (`float`): How much to scale in the x-axis.
 831        y_scale (`float`): How much to scale in the y-axis.
 832    """
 833    ids = _a_canvas.find_withtag(shape)
 834
 835    coord = get_center(shape)
 836
 837    for i in ids
 838        _a_canvas.scale(i, coord[0], coord[1], x_scale, y_scale)
 839
 840
 841def update_color(shape, color):
 842    """
 843    Change the fill color of a tagged object.
 844
 845    Args:
 846        shape (`Shape` or Tag): The shape or tag to re-fill.
 847        color (`str`): A color name or hex code to re-fill with.
 848    """
 849    ids = _a_canvas.find_withtag(shape)
 850    for id in ids
 851        _a_canvas.itemconfig(id, fill=color)
 852
 853
 854def interpolate_colors(color1, color2, frac):
 855    """
 856    A reporter function that generates a new color between two given colors.
 857    Args:
 858        color1 (`str`): The path of the file to wrap
 859        color2 (`str`): The path of the file to wrap
 860        frac (`float`): What fraction of each color to take. An input of 0 returns
 861            color1, an input of 1 returns color2, an input of 0.5 returns a color
 862            perfectly between the two.
 863
 864    Returns:
 865         A color (as a hex `str`) to be used elsewhere
 866    """
 867    if "#" not in color1
 868        color1 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color1)))
 869    else
 870        color1 = _tupelize_color(color1)
 871    if "#" not in color2
 872        color2 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color2)))
 873    else
 874        color2 = _tupelize_color(color2)
 875    return _interpolate_tuple(color1, color2, frac)
 876
 877
 878def get_colors(shape_or_shapes):
 879    """
 880    A reporter function that returns all the colors associated with a tag or list of tags.
 881
 882    Args:
 883        shape_or_shapes (`str`/`Shape` or `List`): the shape/tag or list of shapes/tags you"d like to find the colors of
 884
 885    Returns:
 886        A `List` containing all unique colors associated with that tag(s)
 887    """
 888    all_shapes = []
 889    if not isinstance(shape_or_shapes, ):
 890        shape_or_shapes = [shape_or_shapes]
 891    for shape in shape_or_shapes
 892        all_shapes += _a_canvas.find_withtag(shape)
 893
 894    all_colors = []
 895    for shape in all_shapes
 896        color = _a_canvas.itemcget(shape, "fill")
 897        if color not in all_colors
 898            all_colors.append(color)
 899
 900    return all_colors
 901
 902
 903def get_center(shape):
 904    """
 905    A reporter function calculates the a coordinate at the center of some shape.
 906
 907    Args:
 908        shape (`Shape` or Tag): The shape in question.
 909
 910    Returns:
 911         A `tuple` representing center of the given shape.
 912    """
 913    bbox = _safe_bbox(shape)
 914
 915    if bbox is None
 916        raise Exception(
 917            f"We couldn"t find the shape with id/tag {shape}. Make sure it exists!"
 918        )
 919
 920    return (((bbox[2] + bbox[0]) / 2), ((bbox[1] + bbox[3]) / 2))
 921
 922
 923def get_top(shape):
 924    """
 925    A reporter function calculates the minimum y-value of a given shape (since the y-axis is flipped).
 926
 927    Args:
 928        shape (`Shape` or Tag): The shape in question.
 929
 930    Returns:
 931         A `int` representing the minimum y-coordinate of the shape.
 932    """
 933    bbox = _safe_bbox(shape)
 934    return bbox[1]
 935
 936
 937def get_bottom(shape):
 938    """
 939    A reporter function calculates the maximum y-value of a given shape (since the y-axis is flipped).
 940
 941    Args:
 942        shape (`Shape` or Tag): The shape in question.
 943
 944    Returns:
 945         A `int` representing the maximum y-coordinate of the shape.
 946    """
 947    bbox = _safe_bbox(shape)
 948    return bbox[3]
 949
 950
 951def get_left(shape):
 952    """
 953    A reporter function calculates the minimum x-value of a given shape.
 954
 955    Args:
 956        shape (`Shape` or Tag): The shape in question.
 957
 958    Returns:
 959         A `int` representing the minimum x-coordinate of the shape.
 960    """
 961    bbox = _safe_bbox(shape)
 962    return bbox[0]
 963
 964
 965def get_right(shape):
 966    """
 967    A reporter function calculates the maximum x-value of a given shape.
 968
 969    Args:
 970        shape (`Shape` or Tag): The shape in question.
 971
 972    Returns:
 973         A `int` representing the maximum x-coordinate of the shape.
 974    """
 975    bbox = _safe_bbox(shape)
 976    return bbox[2]
 977
 978
 979def get_height(shape):
 980    """
 981    A reporter function calculates the height of some given shape.
 982
 983    Args:
 984        shape (`Shape` or Tag): The shape in question.
 985
 986    Returns:
 987         A `int` representing the height of the shape.
 988    """
 989    bbox = _safe_bbox(shape)
 990    return bbox[3] - bbox[1] - 1
 991
 992
 993def get_width(shape):
 994    """
 995    A reporter function calculates the width of some given shape.
 996
 997    Args:
 998        shape (`Shape` or Tag): The shape in question.
 999
1000    Returns:
1001         An `int` representing width of the shape.
1002    """
1003    bbox = _safe_bbox(shape)
1004    return bbox[2] - bbox[0] - 1
1005
1006
1007def make_grid(c, w, h):
1008    """
1009    Draws a grid on a screen with intervals of 100.
1010
1011    Args:
1012        w (`int`): The width of the grid to draw
1013        h (`int`): The height of the grid to draw
1014    """
1015    interval = 100
1016    # Creates all vertical lines at intervals of 100
1017    for i in range(0, w, interval):
1018        _a_canvas.create_line(i, 0, i, h, tag="grid_line")
1019    # Creates all horizontal lines at intervals of 100
1020    for i in range(0, h, interval):
1021        _a_canvas.create_line(0, i, w, i, tag="grid_line")
1022    # Creates axis labels
1023    offset = 2
1024    for y in range(0, h, interval):
1025        for x in range(0, w, interval):
1026            _a_canvas.create_oval(
1027                x - offset, y - offset, x + offset, y + offset, fill="black"
1028            )
1029            _a_canvas.create_text(
1030                x + offset,
1031                y + offset,
1032                text="({0}, {1})".format(x, y),
1033                anchor="nw",
1034                font=("Purisa", 8),
1035            )
1036
1037
1038def _safe_bbox(shape):
1039    try
1040        bbox = _a_canvas.bbox(shape)
1041        if bbox is None
1042            Exception(
1043                f"We couldn"t find the shape with tag/id: {shape}. Make sure this shape exists!"
1044            )
1045        return bbox
1046    except
1047        raise Exception(
1048            f"We couldn"t find the shape with tag/id: {shape}. Make sure this shape exists!"
1049        )
1050
1051
1052def _tupelize_color(color):
1053    R = (color[13], 16)
1054    G = (color[35], 16)
1055    B = (color[57], 16)
1056    return R, G, B
1057
1058
1059def _interpolate_tuple(startcolor, goalcolor, frac):
1060    R = startcolor[0]
1061    G = startcolor[1]
1062    B = startcolor[2]
1063
1064    targetR = goalcolor[0]
1065    targetG = goalcolor[1]
1066    targetB = goalcolor[2]
1067
1068    DiffR = targetR - R
1069    DiffG = targetG - G
1070    DiffB = targetB - B
1071
1072    iR = (R + (DiffR * frac))
1073    iG = (G + (DiffG * frac))
1074    iB = (B + (DiffB * frac))
1075
1076    hR = hex(iR).replace("0x", "")
1077    hG = hex(iG).replace("0x", "")
1078    hB = hex(iB).replace("0x", "")
1079
1080    if len(hR) == 1
1081        hR = "0" + hR
1082    if len(hB) == 1
1083        hB = "0" + hB
1084    if len(hG) == 1
1085        hG = "0" + hG
1086
1087    color = ("#" + hR + hG + hB).upper()
1088
1089    return color
1090
1091
1092def does_tag_exist(tag):
1093    """
1094    Returns `True` if a given tag exists otherwise returns `False`.
1095
1096    Args:
1097        `tag` (`str`): [Required] The tag of the object to lookup.
1098
1099    """
1100    result = _a_canvas.find_withtag(tag)
1101
1102    if result
1103        return True
1104    else
1105        return False
1106
1107
1108def random_color():
1109    """
1110    Returns a random color as a `string` to be used with `tkinter`.
1111    It does not accept any inputs.
1112    """
1113    r = lambda randint(0, 255)
1114    return "#%02X%02X%02X" % (r(), r(), r())
1115
1116
1117from tkinter import Tk, Canvas
1118
1119
1120def setup_shapes(title, background="white", grid=True, width=600, height=600):
1121    """
1122    A static function that sets up the pop-up window. DO NOT USE THIS FUNCTION.
1123    """
1124    global _a_canvas
1125    gui = Tk()
1126    gui.title(title)
1127    _a_canvas = Canvas(gui, background=background, width=width, height=width)
1128    _a_canvas.pack()
1129    if grid
1130        make_grid(_a_canvas, width, height)
1131    return _a_canvas
GOOMBA_COLORS = [None, "saddle brown", "black", "tan", "white"]
GOOMBA = [(0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0), (0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0), (0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0), (0, 0, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 0, 0), (0, 1, 1, 1, 4, 2, 1, 1, 1, 1, 2, 4, 1, 1, 1, 0), (0, 1, 1, 1, 4, 2, 2, 2, 2, 2, 2, 4, 1, 1, 1, 0), (1, 1, 1, 1, 4, 2, 4, 1, 1, 4, 2, 4, 1, 1, 1, 1), (1, 1, 1, 1, 4, 4, 4, 1, 1, 4, 4, 4, 1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), (0, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 0), (0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0), (0, 0, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 0, 0), (0, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 2, 0), (0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0), (0, 0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 0, 0)]
def draw_row(row, top_left, colors, pixel=25, tag=""):
23def draw_row(row, top_left, colors, pixel=25, tag=""):
24    """
25    Draws a single row of some pixel art.
26
27    Args:
28        row (sequence): the row of artwork to draw
29        top_left (`tuple`): the top left coordinate of the pixel art
30        color (sequence): the colors to use for each square
31        pixel (`int`, optional): how big each individual pixel should be
32        tag (`str`, optional): the tag to assign to every square in the row
33    """
34    x = top_left[0]
35    y = top_left[1]
36    for cell in row
37        if cell != 0
38            square((x, y), pixel, color=colors[cell], tag=tag)
39        x += pixel

Draws a single row of some pixel art.

Arguments:
  • row (sequence): the row of artwork to draw
  • top_left (tuple): the top left coordinate of the pixel art
  • color (sequence): the colors to use for each square
  • pixel (int, optional): how big each individual pixel should be
  • tag (str, optional): the tag to assign to every square in the row
def pixel_art(top_left, artwork, palette, pixel=10, tag=""):
42def pixel_art(top_left, artwork, palette, pixel=10, tag=""):
43    """
44    Draws a pixel art design!
45
46    Args:
47        top_left (`tuple`): the top left coordinate of the pixel art
48        artwork (sequence of sequences): the art to draw
49        palette (sequence): the palette of colors to use for each different square
50        pixel (`int`, optional): how big each individual pixel should be
51        tag (`str`, optional): the tag to assign to every square in the row
52    """
53    x = top_left[0]
54    y = top_left[1]
55    for row in artwork
56        # draw each row at the specified (x, y) position:
57        draw_row(row, (x, y), colors=palette, pixel=pixel, tag=tag)
58        # ...and don"t forget to shift the y-value down by the proper
59        #  amount so that the next row won"t draw on top of the first one:
60        y += pixel

Draws a pixel art design!

Arguments:
  • top_left (tuple): the top left coordinate of the pixel art
  • artwork (sequence of sequences): the art to draw
  • palette (sequence): the palette of colors to use for each different square
  • pixel (int, optional): how big each individual pixel should be
  • tag (str, optional): the tag to assign to every square in the row
def rectangle( top_left=(0, 0), width=25, height=50, color="hot pink", outline="", tag="",):
77def rectangle(
78    top_left=(0, 0), width=25, height=50, color="hot pink", outline="", tag="", 
79):
80    """
81    A reporter function that draws a rectangle.
82    Args:
83        top_left (`tuple`): A coordinate representing the top left-hand corner of the shape.
84        width (`int`): How wide to draw the shape.
85        height (`int`): How tall to draw the shape.
86        color (`str`): What color to draw the shape.
87        outline (`str`): What color should the border of the shape be.
88        tag (`str`): The tag to assign to the shape.
89
90    Returns:
91         `Shape`: The rectangle that was created.
92    """
93    point_0 = top_left
94    point_1 = (top_left[0] + width, top_left[1])
95    point_2 = (top_left[0] + width, top_left[1] + height)
96    point_3 = (top_left[0], top_left[1] + height)
97    return _a_canvas.create_polygon(
98        point_0, point_1, point_2, point_3, fill=_safe_color(color), tags=tag, 
99    )

A reporter function that draws a rectangle.

Arguments:
  • top_left (tuple): A coordinate representing the top left-hand corner of the shape.
  • width (int): How wide to draw the shape.
  • height (int): How tall to draw the shape.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The rectangle that was created.

def square( top_left=(0, 0), size=25, color="hot pink", outline="", tag="",):
102def square(top_left=(0, 0), size=25, color="hot pink", outline="", tag="", ):
103    """
104    A reporter function that draws a square.
105    Args:
106        top_left (`tuple`): A coordinate representing the top left-hand corner of the shape.
107        size (`int`): How big to draw the shape.
108        color (`str`): What color to draw the shape.
109        outline (`str`): What color should the border of the shape be.
110        tag (`str`): The tag to assign to the shape.
111
112    Returns:
113         `Shape`: The square that was created.
114    """
115    return rectangle(
116        top_left=top_left, width=size, height=size, color=color, tag=tag, 
117    )

A reporter function that draws a square.

Arguments:
  • top_left (tuple): A coordinate representing the top left-hand corner of the shape.
  • size (int): How big to draw the shape.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The square that was created.

def oval( center=(0, 0), radius_x=25, radius_y=50, color="hot pink", outline="", tag="",):
120def oval(
121    center=(0, 0),
122    radius_x=25,
123    radius_y=50,
124    color="hot pink",
125    outline="",
126    tag="",
127    ,
128):
129    """
130    A reporter function that draws an oval.
131    Args:
132        center (`tuple`): A coordinate representing the center of the shape.
133        radius_x (`int`): Specifies the oval"s radius on the x-axis.
134        radius_y (`int`): Specifies the oval"s radius on the y-axis.
135        color (`str`): What color to draw the shape.
136        outline (`str`): What color should the border of the shape be.
137        tag (`str`): The tag to assign to the shape.
138
139    Returns:
140         `Shape`: The oval that was created.
141    """
142    x = center[0]
143    y = center[1]
144    x0, y0, x1, y1 = (x - radius_x, y - radius_y, x + radius_x, y + radius_y)
145    steps = 100
146    # major and minor axes
147    a = (x1 - x0) / 2.0
148    b = (y1 - y0) / 2.0
149    # center
150    xc = x0 + a
151    yc = y0 + b
152    point_list = []
153    # create the oval as a list of points
154    for i in range(steps):
155        # Calculate the angle for this step
156        theta = (pi * 2) * (float(i) / steps)
157        x = a * cos(theta)
158        y = b * sin(theta)
159        point_list.append(round(x + xc))
160        point_list.append(round(y + yc))
161
162    return _a_canvas.create_polygon(
163        point_list, fill=_safe_color(color), tags=tag, 
164    )

A reporter function that draws an oval.

Arguments:
  • center (tuple): A coordinate representing the center of the shape.
  • radius_x (int): Specifies the oval's radius on the x-axis.
  • radius_y (int): Specifies the oval's radius on the y-axis.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The oval that was created.

def circle( center=(0, 0), radius=25, color="hot pink", outline="", tag="",):
167def circle(center=(0, 0), radius=25, color="hot pink", outline="", tag="", ):
168    """
169    A reporter function that draws a circle.
170    Args:
171        center (`tuple`): A coordinate representing the center of the shape.
172        radius (`int`): Specifies the circle"s radius.
173        color (`str`): What color to draw the shape.
174        outline (`str`): What color should the border of the shape be.
175        tag (`str`): The tag to assign to the shape.
176
177    Returns:
178         `Shape`: The circle that was created.
179    """
180    return oval(
181        center=center, radius_x=radius, radius_y=radius, color=color, tag=tag, 
182    )

A reporter function that draws a circle.

Arguments:
  • center (tuple): A coordinate representing the center of the shape.
  • radius (int): Specifies the circle's radius.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The circle that was created.

def cloud(center=(0, 0), size=30, color="white", tag=""):
185def cloud(center=(0, 0), size=30, color="white", tag=""):
186    """
187    Reporter function that draws a cloud to the screen.
188    Args:
189        enter (`tuple`): the point on which to center the cloud
190        color (`str`): which determines the color of the cloud
191        tag (`str`): to give the cloud a name
192
193    Returns:
194        `Shape`: The cloud that was created.
195    """
196    for i in range(10):
197        x_offset = randint((-1 * size * 1.333), (size * 1.333))
198        y_offset = randint(0, (size * 0.667))
199        circle(
200            center=(center[0] + x_offset, center[1] + y_offset),
201            radius=randint((size * 0.667), (size * 1.667)),
202            color=color,
203            tag=tag,
204        )
205    return tag

Reporter function that draws a cloud to the screen.

Arguments:
  • enter (tuple): the point on which to center the cloud
  • color (str): which determines the color of the cloud
  • tag (str): to give the cloud a name
Returns:

Shape: The cloud that was created.

def wedge( center=(0, 0), radius=25, angle=180, color="hot pink", outline="", tag="",):
208def wedge(
209    center=(0, 0), radius=25, angle=180, color="hot pink", outline="", tag="", 
210):
211    """
212    A reporter function that draws a circle.
213    Args:
214        center (`tuple`): A coordinate representing the center of the shape.
215        radius (`int`): Specifies the circle"s radius.
216        angle (`int`): A number between 0 and 360 that specifies how much of the circle to draw.
217        color (`str`): What color to draw the shape.
218        outline (`str`): What color should the border of the shape be.
219        tag (`str`): The tag to assign to the shape.
220
221    Returns:
222         `Shape`: The wedge that was created.
223    """
224    point_list = [center[0], center[1]]
225    for i in range(0, 0 + angle):
226        x1 = center[0] + radius * cos(radians(i))
227        point_list.append(x1)
228        y1 = center[1] + radius * sin(radians(i))
229        point_list.append(y1)
230
231    point_list.append(center[0])
232    point_list.append(center[1])
233
234    return _a_canvas.create_polygon(
235        point_list, fill=_safe_color(color), outline=outline, tags=tag, 
236    )

A reporter function that draws a circle.

Arguments:
  • center (tuple): A coordinate representing the center of the shape.
  • radius (int): Specifies the circle's radius.
  • angle (int): A number between 0 and 360 that specifies how much of the circle to draw.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The wedge that was created.

def triangle( bottom_center=(0, 0), width=25, top_shift=0, height=0, color="hot pink", outline="", tag="",):
239def triangle(
240    bottom_center=(0, 0),
241    width=25,
242    top_shift=0,
243    height=0,
244    color="hot pink",
245    outline="",
246    tag="",
247    ,
248):
249    """
250    A reporter function that draws a triangle.
251    Args:
252        bottom_center (`tuple`): A coordinate representing the bottom center of the shape.
253        width (`int`): Specifies the width of the base of the triangle.
254        top_shift (`int`): Specifies the how far to the left or right to shift the top of
255            the triangle from the bottom center.
256        height (`int`): Specifies the triangle"s height.
257        color (`str`): What color to draw the shape.
258        outline (`str`): What color should the border of the shape be.
259        tag (`str`): The tag to assign to the shape.
260
261    Returns:
262         `Shape`: The triangle that was created.
263    """
264    if height == 0
265        height = width * sqrt(3) / 2
266    point_0 = (bottom_center[0] - width / 2, bottom_center[1])
267    point_1 = (bottom_center[0] + width / 2, bottom_center[1])
268    point_2 = (bottom_center[0] + top_shift, bottom_center[1] - height)
269
270    return _a_canvas.create_polygon(
271        point_0, point_1, point_2, fill=_safe_color(color), tags=tag, 
272    )

A reporter function that draws a triangle.

Arguments:
  • bottom_center (tuple): A coordinate representing the bottom center of the shape.
  • width (int): Specifies the width of the base of the triangle.
  • top_shift (int): Specifies the how far to the left or right to shift the top of the triangle from the bottom center.
  • height (int): Specifies the triangle's height.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The triangle that was created.

def line(points=[], curvy=False, color="hot pink", tag="", ):
275def line(points=[], curvy=False, color="hot pink", tag="", ):
276    """
277    A reporter function that draws a line given a list of points.
278    Args:
279        points (`list`): The points that define the line; this should be a list of tuples (coordinates).
280        curvy (`bool`): Makes a curvy line instead.
281        color (`str`): What color to make the shape.
282        tag (`str`): The tag to assign to the shape.
283
284    Returns:
285        `Shape`: The line that was created.
286    """
287    return _a_canvas.create_line(points, fill=color, smooth=curvy, tags=tag, )

A reporter function that draws a line given a list of points.

Arguments:
  • points (list): The points that define the line; this should be a list of tuples (coordinates).
  • curvy (bool): Makes a curvy line instead.
  • color (str): What color to make the shape.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The line that was created.

def arc( points=[], width=5, color="hot pink", line_steps=15, tag="",):
290def arc(points=[], width=5, color="hot pink", line_steps=15, tag="", ):
291    """
292    A reporter function that draws an arc ("curve") given a list of points.
293    Args:
294        points (`list`): The points outlining the curve; this should be a list of tuples (coordinates).
295            Make sure to give it at least 3 (x,y) coordinates that aren"t a straight line!
296        color (`str`): What color to make the shape.
297        tag (`str`): The tag to assign to the shape.
298
299    Returns:
300        `Shape`: The arc that was created.
301    """
302    return _a_canvas.create_line(
303        points,
304        width=width,
305        fill=color,
306        splinesteps=line_steps,
307        smooth=True,
308        tags=tag,
309        ,
310    )

A reporter function that draws an arc ("curve") given a list of points.

Arguments:
  • points (list): The points outlining the curve; this should be a list of tuples (coordinates). Make sure to give it at least 3 (x,y) coordinates that aren't a straight line!
  • color (str): What color to make the shape.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The arc that was created.

def diamond( center=(0, 0), width=25, height=50, color="hot pink", outline="", tag="",):
313def diamond(
314    center=(0, 0), width=25, height=50, color="hot pink", outline="", tag="", 
315):
316    """
317    A reporter function that draws a rectangle.
318    Args:
319        center (`tuple`): A coordinate representing the center of the shape.
320        width (`int`): How wide to draw the shape.
321        height (`int`): How tall to draw the shape.
322        color (`str`): What color to draw the shape.
323        outline (`str`): What color should the border of the shape be.
324        tag (`str`): The tag to assign to the shape.
325
326    Returns:
327         `Shape`: The shape that was created.
328    """
329    point_0 = (center[0] - width / 2, center[1])
330    point_1 = (center[0], center[1] - height / 2)
331    point_2 = (center[0] + width / 2, center[1])
332    point_3 = (center[0], center[1] + height / 2)
333    return _a_canvas.create_polygon(
334        point_0,
335        point_1,
336        point_2,
337        point_3,
338        fill=_safe_color(color),
339        tags=tag,
340        outline=outline,
341        ,
342    )

A reporter function that draws a rectangle.

Arguments:
  • center (tuple): A coordinate representing the center of the shape.
  • width (int): How wide to draw the shape.
  • height (int): How tall to draw the shape.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The shape that was created.

def star( center=(0, 0), radius=50, color="hot pink", outer_radius=75, points=5, outline="", tag="",):
345def star(
346    center=(0, 0),
347    radius=50,
348    color="hot pink",
349    outer_radius=75,
350    points=5,
351    outline="",
352    tag="",
353    ,
354):
355    """
356    A reporter function that draws a star.
357    Args:
358        center (`tuple`): A coordinate representing the center of the shape.
359        radius (`int`): Specifies the radius of the inside part of the star.
360        color (`str`): Specifies the color of the star.
361        outer_radius (`int`): Specifies the radius of the outside part of the star.
362        points (`int`): Specifies the number of points for the star.
363        outline (`str`): What color should the border of the shape be.
364        tag (`str`): The tag to assign to the shape.
365
366    Returns:
367         `Shape`: The star that was created.
368    """
369    arc_segment = 360 / points
370    vertices = []
371    for i in range(points):
372        inner_point = (
373            radius * cos(radians(arc_segment * i)) + center[0],
374            -1 * radius * sin(radians(arc_segment * i)) + center[1],
375        )
376        vertices.append(inner_point)
377        outer_point = (
378            outer_radius * cos(radians(arc_segment * i + arc_segment / 2)) + center[0],
379            -1 * outer_radius * sin(radians(arc_segment * i + arc_segment / 2))
380            + center[1],
381        )
382        vertices.append(outer_point)
383    return polygon(vertices, color=color, tag=tag, )

A reporter function that draws a star.

Arguments:
  • center (tuple): A coordinate representing the center of the shape.
  • radius (int): Specifies the radius of the inside part of the star.
  • color (str): Specifies the color of the star.
  • outer_radius (int): Specifies the radius of the outside part of the star.
  • points (int): Specifies the number of points for the star.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The star that was created.

def polygon(points=[], color="hot pink", outline="", tag="", ):
386def polygon(points=[], color="hot pink", outline="", tag="", ):
387    """
388    A reporter function that draws a polygon given a list of points.
389    Args:
390        points (`list`): The points outlining the polygon; this should be a list of tuples (coordinates).
391            defaults to an empty list.
392        outline (`str`): What color should the border of the shape be.
393        color (`str`): What color to make the shape.
394
395    Returns:
396        `Shape`: The polygon that was created.
397    """
398    return _a_canvas.create_polygon(points, fill=_safe_color(color), tags=tag, )

A reporter function that draws a polygon given a list of points.

Arguments:
  • points (list): The points outlining the polygon; this should be a list of tuples (coordinates). defaults to an empty list.
  • outline (str): What color should the border of the shape be.
  • color (str): What color to make the shape.
Returns:

Shape: The polygon that was created.

def spiral( center=(0, 0), width=100, roughness=0.01, start=0, spirals=5, line_width=1,):
405def spiral(
406    center=(0, 0), width=100, roughness=0.01, start=0, spirals=5, line_width=1, 
407):
408    """
409    A reporter function that draws a spiral.
410    Args:
411        center (`tuple`): A coordinate representing the center of the shape.
412        width (`int`): Specifies the total width of the spiral.
413        roughness (`float`): Controls how spiral-y the shape is (lower is less spiral-y)
414        start (`int`): Where on the spiral to start drawing.
415        spirals (`int`): How many loops to draw.
416        line_width (`int`): How wide for the line to be drawn.
417        tag (`str`): The tag to assign to the shape.
418
419    Returns:
420         `Shape`: The spiral that was created.
421    """
422    theta = 0.0
423    r = start
424    all_points = []
425    prev_pos = _polar_to_cartesian(r, theta)
426    distance = width / 4 / pi / spirals
427    all_points.append((prev_pos[0] + center[0], prev_pos[1] + center[1]))
428    while theta < 2 * spirals * pi
429        theta += roughness
430        r = start + distance * theta
431        pos = _polar_to_cartesian(r, theta)
432        all_points.append((pos[0] + center[0], pos[1] + center[1]))
433
434    return arc(points=all_points, width=line_width, )

A reporter function that draws a spiral.

Arguments:
  • center (tuple): A coordinate representing the center of the shape.
  • width (int): Specifies the total width of the spiral.
  • roughness (float): Controls how spiral-y the shape is (lower is less spiral-y)
  • start (int): Where on the spiral to start drawing.
  • spirals (int): How many loops to draw.
  • line_width (int): How wide for the line to be drawn.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The spiral that was created.

def move(shape, x_shift=0, y_shift=0):
437def move(shape, x_shift=0, y_shift=0):
438    """
439    Purpose: Move the x and y position of all shapes that have been tagged
440    with the tag argument
441
442    Args:
443        shape (`Shape` or Tag): The shape in question.
444        x_shift (`int`; optional): amount to move in the x direction
445        y_shift (`int`; optional): amount to move in the y direction
446    """
447    shape_ids = _a_canvas.find_withtag(shape)
448    for id in shape_ids
449        _a_canvas.move(id, x_shift, y_shift)

Purpose: Move the x and y position of all shapes that have been tagged with the tag argument

Arguments:
  • shape (Shape or Tag): The shape in question.
  • x_shift (int; optional): amount to move in the x direction
  • y_shift (int; optional): amount to move in the y direction
def portion(shape, start=0, end=0.5):
452def portion(shape, start=0, end=0.5):
453    """
454    Purpose: Take a slice or portion of some already created shape.
455
456    Args:
457        shape (`Shape` or Tag): The shape to take a portion of
458        start (`float`): A number between 0 and 1 representing where to start the slice.
459        end (`float`): A number between 0 and 1 representing where to end the slice.
460
461    For example, taking a portion from 0 to 0.5 of a circle would result in a semi-circle.
462
463    Note: this function is experimental. It might produce unexpected results!
464    """
465    all_shapes = _a_canvas.find_withtag(shape)
466
467    for a_shape in all_shapes
468        coords = _a_canvas.coords(a_shape)
469
470        start_coord = floor(start * len(coords))
471        if start_coord % 2 == 1
472            start_coord = start_coord - 1  # need to start with an x,y pair
473        end_coord = floor(end * len(coords))
474        if end_coord % 2 == 1
475            end_coord = end_coord - 1  # need to end with an x,y pair
476
477        # slice is up to not including so get the last x,y pair
478        new_coords = coords[start_coord  end_coord + 2]
479
480        # loop shape back in on itself
481        new_coords.append(new_coords[0])
482        new_coords.append(new_coords[1])
483
484        # set the coordinates:
485        _a_canvas.coords(a_shape, new_coords)

Purpose: Take a slice or portion of some already created shape.

Arguments:
  • shape (Shape or Tag): The shape to take a portion of
  • start (float): A number between 0 and 1 representing where to start the slice.
  • end (float): A number between 0 and 1 representing where to end the slice.

For example, taking a portion from 0 to 0.5 of a circle would result in a semi-circle.

Note: this function is experimental. It might produce unexpected results!

def put_in_front(shape):
488def put_in_front(shape):
489    """
490    A function that "raises" a shape to the "top" of the screen."
491
492    Args:
493        shape (`Shape` or Tag): The shape in question.
494    """
495    _a_canvas.tag_raise(shape)

A function that "raises" a shape to the "top" of the screen."

Arguments:
  • shape (Shape or Tag): The shape in question.
def put_in_back(shape):
498def put_in_back(shape):
499    """
500    A function that "lowers" a shape to the "bottom" of the screen."
501
502    Args:
503        shape (`Shape` or Tag): The shape in question.
504    """
505    _a_canvas.tag_lower(shape)

A function that "lowers" a shape to the "bottom" of the screen."

Arguments:
  • shape (Shape or Tag): The shape in question.
def align(shape1, shape2, via="middle", offset_x=0, offset_y=0):
529def align(shape1, shape2, via="middle", offset_x=0, offset_y=0):
530    """
531    A reporter function that aligns `shape1` with `shape2`. It does this by moving `shape1` to align with
532    whatever property of `shape2` is selected with the `via` input.
533
534    Args:
535        shape1 (`Shape` or Tag): The first shape to use.
536        shape2 (`Shape` or Tag): The second shape to use.
537        via (`str`): Has to be one of, the following options: `"center"` (horizontal center),
538            `"middle"` (vertical center), `"top"`, `"bottom"`, `"left"`, or `"right"`
539        offset_x (`int`): How much to shift in the x-axis after alignment
540        offset_y (`int`): How much to shift in the y-axis after alignment
541
542    Returns:
543        `Shape`: The modified shape1.
544    """
545    via_options = ["center", "middle", "top", "bottom", "left", "right"]
546    if via not in via_options
547        raise ValueError(
548            "The via input must be one of "
549            + (via_options)
550            + " but instead we found "
551            + (via)
552        )
553
554    outline1 = _get_outline(shape1)
555    outline2 = _get_outline(shape2)
556
557    if via == "center"
558        _a_canvas.move(
559            shape1, (outline2["center"][0] - outline1["center"][0]) + offset_x, offset_y
560        )
561
562    elif via == "middle"
563        _a_canvas.move(
564            shape1, offset_x, (outline2["center"][1] - outline1["center"][1]) + offset_y
565        )
566
567    elif via == "top"
568        _a_canvas.move(shape1, offset_x, (outline2["top"] - outline1["top"]) + offset_y)
569
570    elif via == "bottom"
571        _a_canvas.move(
572            shape1, offset_x, (outline2["bottom"] - outline1["bottom"]) + offset_y
573        )
574
575    elif via == "left"
576        _a_canvas.move(
577            shape1, (outline2["left"] - outline1["left"]) + offset_x, offset_y
578        )
579
580    elif via == "right"
581        _a_canvas.move(
582            shape1, (outline2["right"] - outline1["right"]) + offset_x, offset_y
583        )
584
585    return shape1

A reporter function that aligns shape1 with shape2. It does this by moving shape1 to align with whatever property of shape2 is selected with the via input.

Arguments:
  • shape1 (Shape or Tag): The first shape to use.
  • shape2 (Shape or Tag): The second shape to use.
  • via (str): Has to be one of, the following options: "center" (horizontal center), "middle" (vertical center), "top", "bottom", "left", or "right"
  • offset_x (int): How much to shift in the x-axis after alignment
  • offset_y (int): How much to shift in the y-axis after alignment
Returns:

Shape: The modified shape1.

def overlay(shape1, shape2, offset_x=0, offset_y=0):
588def overlay(shape1, shape2, offset_x=0, offset_y=0):
589    """
590    A reporter function that overlays shape1 onto shape2. It does this by moving shape 1"s center
591    to shape 2"s center, and then applying any specified offset.
592    Args:
593        shape1 (`Shape` or Tag): The first shape to use.
594        shape2 (`Shape` or Tag): The second shape to use.
595        offset_x (`int`): How much to shift shape 2 in the x-direction after centering it.
596        offset_y (`int`): How much to shift shape 2 in the x-direction after centering it.
597
598    Returns:
599        `Shape`: The modified shape1.
600    """
601    center1 = get_center(shape1)
602    center2 = get_center(shape2)
603    _a_canvas.move(
604        shape1,
605        (center2[0] - center1[0]) + offset_x,
606        (center2[1] - center1[1]) + offset_y,
607    )
608    _a_canvas.tag_raise(shape1, shape2)
609    return shape1

A reporter function that overlays shape1 onto shape2. It does this by moving shape 1's center to shape 2's center, and then applying any specified offset.

Arguments:
  • shape1 (Shape or Tag): The first shape to use.
  • shape2 (Shape or Tag): The second shape to use.
  • offset_x (int): How much to shift shape 2 in the x-direction after centering it.
  • offset_y (int): How much to shift shape 2 in the x-direction after centering it.
Returns:

Shape: The modified shape1.

def underlay(shape1, shape2, offset_x=0, offset_y=0):
612def underlay(shape1, shape2, offset_x=0, offset_y=0):
613    """
614    A reporter function that underlays shape1 beneath shape2. It does this by moving shape 1"s center
615    to shape 2"s center, and then applying any specified offset.
616    Args:
617        shape1 (`Shape` or Tag): The first shape to use.
618        shape2 (`Shape` or Tag): The second shape to use.
619        offset_x (`int`): How much to shift shape 2 in the x-direction after centering it.
620        offset_y (`int`): How much to shift shape 2 in the x-direction after centering it.
621
622    Returns:
623        `Shape`: The modified shape1.
624    """
625    center1 = get_center(shape1)
626    center2 = get_center(shape2)
627    _a_canvas.move(
628        shape1,
629        (center2[0] - center1[0]) + offset_x,
630        (center2[1] - center1[1]) + offset_y,
631    )
632    _a_canvas.tag_lower(shape1, shape2)
633    return shape1

A reporter function that underlays shape1 beneath shape2. It does this by moving shape 1's center to shape 2's center, and then applying any specified offset.

Arguments:
  • shape1 (Shape or Tag): The first shape to use.
  • shape2 (Shape or Tag): The second shape to use.
  • offset_x (int): How much to shift shape 2 in the x-direction after centering it.
  • offset_y (int): How much to shift shape 2 in the x-direction after centering it.
Returns:

Shape: The modified shape1.

def above(shape1, shape2, offset_x=0, offset_y=0):
636def above(shape1, shape2, offset_x=0, offset_y=0):
637    """
638    A reporter function that places shape1 above shape2 (vertically). It does this by moving shape 1"s center
639    to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any
640    specified offset.
641
642    Args:
643        shape1 (`Shape` or Tag): The first shape to use.
644        shape2 (`Shape` or Tag): The second shape to use.
645        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
646        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
647
648    Returns:
649        `Shape`: The modified shape1.
650    """
651    overlay(shape1, shape2)
652    _a_canvas.move(
653        shape1,
654        0 + offset_x,
655        -1 * (get_height(shape2) + get_height(shape1)) / 2 + offset_y,
656    )
657    return shape1

A reporter function that places shape1 above shape2 (vertically). It does this by moving shape 1's center to shape 2's center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any specified offset.

Arguments:
  • shape1 (Shape or Tag): The first shape to use.
  • shape2 (Shape or Tag): The second shape to use.
  • offset_x (int): How much to shift shape 2 in the x-direction after moving it.
  • offset_y (int): How much to shift shape 2 in the x-direction after moving it.
Returns:

Shape: The modified shape1.

def beside(shape1, shape2, offset_x=0, offset_y=0):
660def beside(shape1, shape2, offset_x=0, offset_y=0):
661    """
662    A reporter function that places shape1 beside shape2 (horizontally). It does this by moving shape 1"s center
663    to shape 2"s center, moving shape 1 in the x-direction the exact width of shape 2, and then applying any
664    specified offset.
665
666    Args:
667        shape1 (`Shape` or Tag): The first shape to use.
668        shape2 (`Shape` or Tag): The second shape to use.
669        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
670        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
671
672    Returns:
673        `Shape`: The modified shape1.
674    """
675    overlay(shape1, shape2)
676    _a_canvas.move(
677        shape1,
678        (get_width(shape2) + get_width(shape1)) / 2 + offset_x,
679        0 + offset_y,
680    )
681    return shape1

A reporter function that places shape1 beside shape2 (horizontally). It does this by moving shape 1's center to shape 2's center, moving shape 1 in the x-direction the exact width of shape 2, and then applying any specified offset.

Arguments:
  • shape1 (Shape or Tag): The first shape to use.
  • shape2 (Shape or Tag): The second shape to use.
  • offset_x (int): How much to shift shape 2 in the x-direction after moving it.
  • offset_y (int): How much to shift shape 2 in the x-direction after moving it.
Returns:

Shape: The modified shape1.

def below(shape1, shape2, offset_x=0, offset_y=0):
684def below(shape1, shape2, offset_x=0, offset_y=0):
685    """
686    A reporter function that places shape1 below shape2 (vertically). It does this by moving shape 1"s center
687    to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any
688    specified offset.
689
690    Args:
691        shape1 (`Shape` or Tag): The first shape to use.
692        shape2 (`Shape` or Tag): The second shape to use.
693        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
694        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
695
696    Returns:
697        `Shape`: The modified shape1.
698    """
699    overlay(shape1, shape2)
700    _a_canvas.move(
701        shape1,
702        0 + offset_x,
703        (get_height(shape2) + get_height(shape1)) / 2 + offset_y,
704    )
705    return shape1

A reporter function that places shape1 below shape2 (vertically). It does this by moving shape 1's center to shape 2's center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any specified offset.

Arguments:
  • shape1 (Shape or Tag): The first shape to use.
  • shape2 (Shape or Tag): The second shape to use.
  • offset_x (int): How much to shift shape 2 in the x-direction after moving it.
  • offset_y (int): How much to shift shape 2 in the x-direction after moving it.
Returns:

Shape: The modified shape1.

def delete(shape):
708def delete(shape):
709    """
710    A function that deletes a shape from our screen.
711
712    Args:
713        shape (`Shape` or Tag): The shape to delete.
714    """
715    _a_canvas.delete(shape)

A function that deletes a shape from our screen.

Arguments:
  • shape (Shape or Tag): The shape to delete.
def duplicate(shape, color=None):
718def duplicate(shape, color=None):
719    """
720    A reporter function that perfectly copies a shape and returns that copy.
721
722    Args:
723        shape (`Shape` or Tag): The shape to duplicate.
724        color (`str`): A new color to use with the duplicated shape.
725
726    Returns:
727        `Shape`: The new duplicated shape.
728    """
729    shape_type = _a_canvas.type(shape)
730    shape_config = _a_canvas.itemconfig(shape)
731    shape_coords = _a_canvas.coords(shape)
732    the_copy = None
733    if shape_type == "polygon"
734        new_config = {key shape_config[key][-1] for key in shape_config.keys()}
735        if color != None
736            new_config["fill"] = color
737        the_copy = _a_canvas.create_polygon(shape_coords, new_config)
738        return the_copy

A reporter function that perfectly copies a shape and returns that copy.

Arguments:
  • shape (Shape or Tag): The shape to duplicate.
  • color (str): A new color to use with the duplicated shape.
Returns:

Shape: The new duplicated shape.

def mirror(shape):
741def mirror(shape):
742    """
743    A function that takes a shape and flips it across its vertical
744    axis, returning the modified shape.
745
746    Args:
747        shape (`Shape` or Tag): The shape in question.
748
749    """
750    center = get_center(shape)[0]
751    shape_ids = _a_canvas.find_withtag(shape)
752    for shape_id in shape_ids
753        flipped_coordinates = []
754        shape_coords = _a_canvas.coords(shape_id)
755        counter = 0
756        for num in shape_coords
757            if counter % 2 == 0
758                if num < center
759                    flipped_coordinates.append(num + 2 * (center - num))
760                elif num > center
761                    flipped_coordinates.append(num - 2 * (num - center))
762                else
763                    flipped_coordinates.append(num)
764            else
765                flipped_coordinates.append(num)
766            counter += 1
767        _a_canvas.coords(shape_id, flipped_coordinates)

A function that takes a shape and flips it across its vertical axis, returning the modified shape.

Arguments:
  • shape (Shape or Tag): The shape in question.
def rotate(shape, degrees=5, origin=None):
770def rotate(shape, degrees=5, origin=None):
771    """
772    A reporter function that takes a shape and rotates it by a specified amount around a specified point.
773    It does this by interpolating a polygon around the shape and calculating the shifts of individual
774    points on the edge of the polygon.
775
776    Args:
777        shape (`Shape` or Tag): The shape to rotate.
778        degrees (`int`): The number of degrees to rotate the shape.
779        origin (`tuple`): An `(x,y)` coordinate about which to perform the rotation. Defaults to the center
780            of the given shape.
781
782    Returns:
783        `Shape`: The modified shape.
784    """
785    if origin is None
786        origin = get_center(shape)
787
788    theta = radians(degrees)
789    ox, oy = origin
790
791    all_shapes = _a_canvas.find_withtag(shape)
792
793    for a_shape in all_shapes
794        coords = _a_canvas.coords(a_shape)
795        # update coordinates:
796        for i in range(0, len(coords), 2):
797            px, py = coords[i], coords[i + 1]
798            qx = cos(theta) * (px - ox) - sin(theta) * (py - oy) + ox
799            qy = sin(theta) * (px - ox) + cos(theta) * (py - oy) + oy
800            coords[i] = qx
801            coords[i + 1] = qy
802        # set the coordinates:
803        _a_canvas.coords(a_shape, coords)
804
805    return shape

A reporter function that takes a shape and rotates it by a specified amount around a specified point. It does this by interpolating a polygon around the shape and calculating the shifts of individual points on the edge of the polygon.

Arguments:
  • shape (Shape or Tag): The shape to rotate.
  • degrees (int): The number of degrees to rotate the shape.
  • origin (tuple): An (x,y) coordinate about which to perform the rotation. Defaults to the center of the given shape.
Returns:

Shape: The modified shape.

def distance(point1, point2):
808def distance(point1, point2):
809    """
810    A reporter function calculates the distance between two `(x, y)` coordinates.
811
812    Args:
813        point1 (`tuple`): The first `(x, y)` coordinate.
814        point2 (`tuple`): The second `(x, y)` coordinate.
815
816    Returns:
817         A `float` representing the distance between the two points.
818    """
819    return sqrt(((point1[0] - point2[0])  2) + ((point1[1] - point2[1])  2))

A reporter function calculates the distance between two (x, y) coordinates.

Arguments:
  • point1 (tuple): The first (x, y) coordinate.
  • point2 (tuple): The second (x, y) coordinate.
Returns:

A float representing the distance between the two points.

def scale(shape, x_scale=1.0, y_scale=1.0):
822def scale(shape, x_scale=1.0, y_scale=1.0):
823    """
824    A function that takes a given `Shape` or tag and scales it on either/both the x and y-axis.
825
826    The two optional inputs accept floats between 0.0 and 1.0. Values greater than 1 will cause
827    the shape to grow along that access. Values less than 1.0 will cause the shape to shrink.
828
829    Args:
830        shape (`Shape` or Tag): The shape or tag to re-fill.
831        x_scale (`float`): How much to scale in the x-axis.
832        y_scale (`float`): How much to scale in the y-axis.
833    """
834    ids = _a_canvas.find_withtag(shape)
835
836    coord = get_center(shape)
837
838    for i in ids
839        _a_canvas.scale(i, coord[0], coord[1], x_scale, y_scale)

A function that takes a given Shape or tag and scales it on either/both the x and y-axis.

The two optional inputs accept floats between 0.0 and 1.0. Values greater than 1 will cause the shape to grow along that access. Values less than 1.0 will cause the shape to shrink.

Arguments:
  • shape (Shape or Tag): The shape or tag to re-fill.
  • x_scale (float): How much to scale in the x-axis.
  • y_scale (float): How much to scale in the y-axis.
def update_color(shape, color):
842def update_color(shape, color):
843    """
844    Change the fill color of a tagged object.
845
846    Args:
847        shape (`Shape` or Tag): The shape or tag to re-fill.
848        color (`str`): A color name or hex code to re-fill with.
849    """
850    ids = _a_canvas.find_withtag(shape)
851    for id in ids
852        _a_canvas.itemconfig(id, fill=color)

Change the fill color of a tagged object.

Arguments:
  • shape (Shape or Tag): The shape or tag to re-fill.
  • color (str): A color name or hex code to re-fill with.
def interpolate_colors(color1, color2, frac):
855def interpolate_colors(color1, color2, frac):
856    """
857    A reporter function that generates a new color between two given colors.
858    Args:
859        color1 (`str`): The path of the file to wrap
860        color2 (`str`): The path of the file to wrap
861        frac (`float`): What fraction of each color to take. An input of 0 returns
862            color1, an input of 1 returns color2, an input of 0.5 returns a color
863            perfectly between the two.
864
865    Returns:
866         A color (as a hex `str`) to be used elsewhere
867    """
868    if "#" not in color1
869        color1 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color1)))
870    else
871        color1 = _tupelize_color(color1)
872    if "#" not in color2
873        color2 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color2)))
874    else
875        color2 = _tupelize_color(color2)
876    return _interpolate_tuple(color1, color2, frac)

A reporter function that generates a new color between two given colors.

Arguments:
  • color1 (str): The path of the file to wrap
  • color2 (str): The path of the file to wrap
  • frac (float): What fraction of each color to take. An input of 0 returns color1, an input of 1 returns color2, an input of 0.5 returns a color perfectly between the two.
Returns:

A color (as a hex str) to be used elsewhere

def get_colors(shape_or_shapes):
879def get_colors(shape_or_shapes):
880    """
881    A reporter function that returns all the colors associated with a tag or list of tags.
882
883    Args:
884        shape_or_shapes (`str`/`Shape` or `List`): the shape/tag or list of shapes/tags you"d like to find the colors of
885
886    Returns:
887        A `List` containing all unique colors associated with that tag(s)
888    """
889    all_shapes = []
890    if not isinstance(shape_or_shapes, ):
891        shape_or_shapes = [shape_or_shapes]
892    for shape in shape_or_shapes
893        all_shapes += _a_canvas.find_withtag(shape)
894
895    all_colors = []
896    for shape in all_shapes
897        color = _a_canvas.itemcget(shape, "fill")
898        if color not in all_colors
899            all_colors.append(color)
900
901    return all_colors

A reporter function that returns all the colors associated with a tag or list of tags.

Arguments:
  • shape_or_shapes (str/Shape or List): the shape/tag or list of shapes/tags you'd like to find the colors of
Returns:

A List containing all unique colors associated with that tag(s)

def get_center(shape):
904def get_center(shape):
905    """
906    A reporter function calculates the a coordinate at the center of some shape.
907
908    Args:
909        shape (`Shape` or Tag): The shape in question.
910
911    Returns:
912         A `tuple` representing center of the given shape.
913    """
914    bbox = _safe_bbox(shape)
915
916    if bbox is None
917        raise Exception(
918            f"We couldn"t find the shape with id/tag {shape}. Make sure it exists!"
919        )
920
921    return (((bbox[2] + bbox[0]) / 2), ((bbox[1] + bbox[3]) / 2))

A reporter function calculates the a coordinate at the center of some shape.

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

A tuple representing center of the given shape.

def get_top(shape):
924def get_top(shape):
925    """
926    A reporter function calculates the minimum y-value of a given shape (since the y-axis is flipped).
927
928    Args:
929        shape (`Shape` or Tag): The shape in question.
930
931    Returns:
932         A `int` representing the minimum y-coordinate of the shape.
933    """
934    bbox = _safe_bbox(shape)
935    return bbox[1]

A reporter function calculates the minimum y-value of a given shape (since the y-axis is flipped).

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

A int representing the minimum y-coordinate of the shape.

def get_bottom(shape):
938def get_bottom(shape):
939    """
940    A reporter function calculates the maximum y-value of a given shape (since the y-axis is flipped).
941
942    Args:
943        shape (`Shape` or Tag): The shape in question.
944
945    Returns:
946         A `int` representing the maximum y-coordinate of the shape.
947    """
948    bbox = _safe_bbox(shape)
949    return bbox[3]

A reporter function calculates the maximum y-value of a given shape (since the y-axis is flipped).

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

A int representing the maximum y-coordinate of the shape.

def get_left(shape):
952def get_left(shape):
953    """
954    A reporter function calculates the minimum x-value of a given shape.
955
956    Args:
957        shape (`Shape` or Tag): The shape in question.
958
959    Returns:
960         A `int` representing the minimum x-coordinate of the shape.
961    """
962    bbox = _safe_bbox(shape)
963    return bbox[0]

A reporter function calculates the minimum x-value of a given shape.

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

A int representing the minimum x-coordinate of the shape.

def get_right(shape):
966def get_right(shape):
967    """
968    A reporter function calculates the maximum x-value of a given shape.
969
970    Args:
971        shape (`Shape` or Tag): The shape in question.
972
973    Returns:
974         A `int` representing the maximum x-coordinate of the shape.
975    """
976    bbox = _safe_bbox(shape)
977    return bbox[2]

A reporter function calculates the maximum x-value of a given shape.

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

A int representing the maximum x-coordinate of the shape.

def get_height(shape):
980def get_height(shape):
981    """
982    A reporter function calculates the height of some given shape.
983
984    Args:
985        shape (`Shape` or Tag): The shape in question.
986
987    Returns:
988         A `int` representing the height of the shape.
989    """
990    bbox = _safe_bbox(shape)
991    return bbox[3] - bbox[1] - 1

A reporter function calculates the height of some given shape.

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

A int representing the height of the shape.

def get_width(shape):
 994def get_width(shape):
 995    """
 996    A reporter function calculates the width of some given shape.
 997
 998    Args:
 999        shape (`Shape` or Tag): The shape in question.
1000
1001    Returns:
1002         An `int` representing width of the shape.
1003    """
1004    bbox = _safe_bbox(shape)
1005    return bbox[2] - bbox[0] - 1

A reporter function calculates the width of some given shape.

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

An int representing width of the shape.

def make_grid(c, w, h):
1008def make_grid(c, w, h):
1009    """
1010    Draws a grid on a screen with intervals of 100.
1011
1012    Args:
1013        w (`int`): The width of the grid to draw
1014        h (`int`): The height of the grid to draw
1015    """
1016    interval = 100
1017    # Creates all vertical lines at intervals of 100
1018    for i in range(0, w, interval):
1019        _a_canvas.create_line(i, 0, i, h, tag="grid_line")
1020    # Creates all horizontal lines at intervals of 100
1021    for i in range(0, h, interval):
1022        _a_canvas.create_line(0, i, w, i, tag="grid_line")
1023    # Creates axis labels
1024    offset = 2
1025    for y in range(0, h, interval):
1026        for x in range(0, w, interval):
1027            _a_canvas.create_oval(
1028                x - offset, y - offset, x + offset, y + offset, fill="black"
1029            )
1030            _a_canvas.create_text(
1031                x + offset,
1032                y + offset,
1033                text="({0}, {1})".format(x, y),
1034                anchor="nw",
1035                font=("Purisa", 8),
1036            )

Draws a grid on a screen with intervals of 100.

Arguments:
  • w (int): The width of the grid to draw
  • h (int): The height of the grid to draw
def does_tag_exist(tag):
1093def does_tag_exist(tag):
1094    """
1095    Returns `True` if a given tag exists otherwise returns `False`.
1096
1097    Args:
1098        `tag` (`str`): [Required] The tag of the object to lookup.
1099
1100    """
1101    result = _a_canvas.find_withtag(tag)
1102
1103    if result
1104        return True
1105    else
1106        return False

Returns True if a given tag exists otherwise returns False.

Arguments:
  • tag (str): [Required] The tag of the object to lookup.
def random_color():
1109def random_color():
1110    """
1111    Returns a random color as a `string` to be used with `tkinter`.
1112    It does not accept any inputs.
1113    """
1114    r = lambda randint(0, 255)
1115    return "#%02X%02X%02X" % (r(), r(), r())

Returns a random color as a string to be used with tkinter. It does not accept any inputs.

def setup_shapes(title, background="white", grid=True, width=600, height=600):
1121def setup_shapes(title, background="white", grid=True, width=600, height=600):
1122    """
1123    A static function that sets up the pop-up window. DO NOT USE THIS FUNCTION.
1124    """
1125    global _a_canvas
1126    gui = Tk()
1127    gui.title(title)
1128    _a_canvas = Canvas(gui, background=background, width=width, height=width)
1129    _a_canvas.pack()
1130    if grid
1131        make_grid(_a_canvas, width, height)
1132    return _a_canvas

A static function that sets up the pop-up window. DO NOT USE THIS FUNCTION.