commit ff58b527de7a8a01a9360b154231846aba3dd156 Author: = <=> Date: Wed Feb 7 14:24:48 2024 +0100 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d5311d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/workspace.code-workspace +/__pycache__ \ No newline at end of file diff --git a/aztecDiamond.py b/aztecDiamond.py new file mode 100644 index 0000000..44771fc --- /dev/null +++ b/aztecDiamond.py @@ -0,0 +1,286 @@ +from tile import Tile +from tuple_addition import tuple_add as tAdd +from tkinter import Canvas, Frame, BOTH +from random import random + +class AztecDiamond(Frame): + + def __init__(self, x, y): + super().__init__() + self.n = 1 + self.tiles = [] + self.dimensions = (x, y) + self.color_neutral = "orange" + self.triag_color = "black" + self.direction_colors = ["red", "green", "yellow", "blue"] + self.direction_colored = False + self.black = True + self.initialize_draw() + self.init_tiles() + self.place() + + def init_tiles(self): + i = random() + if i < 0.5: + self.tiles.append(Tile((0, 0), (0, -1), (1, 0))) + self.tiles.append(Tile((-1, 0), (-1, -1), (-1, 0))) + else: + self.tiles.append(Tile((0, 0), (-1, 0), (0, 1))) + self.tiles.append(Tile((0, -1), (-1, -1), (0, -1))) + + def grow(self): + shift_dict = {} # dict that maps tile sources to shift directions to determine if two tiles shifted over each other + free_tiles = [] # list that tracks all tiles that are free to fill + + self.n = self.n + 1 + n = self.n + + # register newgrown tiles + for i in range(n): + free_tiles.append((i, n-i-1)) + free_tiles.append((-i-1, i-n)) + free_tiles.append((i, -n+i)) + free_tiles.append((i-n, i)) + # register all tiles that will be shifting away as free (after the shift), and store the direction the shift will happen + for tile in self.tiles: + shift_dict[tile.coord_black] = tile.direction + shift_dict[tile.coord_white] = tile.direction + free_tiles.append(tile.coord_black) + free_tiles.append(tile.coord_white) + # performs the tile-shift and check for tiles that shifted over one another + tiles_to_remove = [] + for tile in self.tiles: + (c1, c2) = tile.shift() + a = (0,0) + b = (0,0) + try: + a = shift_dict[tile.coord_black] + b = shift_dict[tile.coord_white] + except: + pass + if (tAdd(a, tile.direction) == (0,0)) | (tAdd(b, tile.direction) == (0,0)): + tiles_to_remove.append(tile) + else: + if c1 in free_tiles: + free_tiles.remove(c1) + if c2 in free_tiles: + free_tiles.remove(c2) + for tile in tiles_to_remove: + self.tiles.remove(tile) + while True: + # finds corners that correspond to squares that will have to be filled + corners = {} + for field in free_tiles: + x = field[0] + y = field[1] + if not((x,y-1) in free_tiles): + if not((x-1,y) in free_tiles): + corners[(x,y)] = (x+1,y+1) + if not((x+1,y) in free_tiles): + corners[(x,y)] = (x-1,y+1) + elif not((x,y+1) in free_tiles): + if not((x-1,y) in free_tiles): + corners[(x,y)] = (x+1,y-1) + if not((x+1,y) in free_tiles): + corners[(x,y)] = (x-1,y-1) + # fills found squares with new tiles + worked_on = [] + for corner in corners: + i = random() + (x, y) = corner + (m, n) = corners[corner] + if (x,y) in worked_on: + continue + if i < 0.5: + if x < m: + direction_x = (-1, 0) + direction_m = (1, 0) + else: + direction_x = (1, 0) + direction_m = (-1, 0) + self.tiles.append(Tile((x, y), (x, n), direction_x)) + self.tiles.append(Tile((m, y), (m, n), direction_m)) + else: + if y < n: + direction_y = (0, -1) + direction_n = (0, 1) + else: + direction_y = (0, 1) + direction_n = (0, -1) + self.tiles.append(Tile((x, y), (m, y), (direction_y))) + self.tiles.append(Tile((x, n), (m, n), (direction_n))) + worked_on.append((x,y)) + worked_on.append((x,n)) + worked_on.append((m,y)) + worked_on.append((m,n)) + for coord in worked_on: + free_tiles.remove(coord) + if len(free_tiles) == 0: + break + + def grow_and_draw(self): + self.grow() + self.place() + + def initialize_draw(self): + self.initialize_draw_constants() + self.master.title("Aztec Diamond") + self.pack(fill=BOTH, expand=1) + self.canvas = Canvas(self) + self.canvas.pack(fill=BOTH, expand=1) + + def initialize_draw_constants(self): + (x, y) = self.dimensions + self.alpha = 0.9 + self.available_size = round(min(x, y)*self.alpha) + self.corner = ((x-self.available_size)/2, (y-self.available_size)/2) + + def place(self): + self.canvas.delete("all") + + (x, y) = self.corner + dim = self.available_size + n = self.n + stepping = dim/(2*n) + + if self.black: + self.draw_line_frame(0.12, x, y, dim, n, stepping) + self.draw_tiles(0.14, x, y, dim, stepping) + + self.canvas.pack(fill=BOTH, expand=1) + + def draw_line_frame(self, thickness, x, y, dim, n, stepping): + self.canvas.create_line( + x+dim/2, + y, + x+dim/2, + y+dim, + width=thickness*stepping + ) + self.canvas.create_line( + x, + y+dim/2, + x+dim, + y+dim/2, + width=thickness*stepping + ) + for i in range(n): + self.canvas.create_rectangle( + x+stepping*i, + y+stepping*(n-i-1), + x+stepping*(2*n-i), + y+stepping*(n+i+1), + width=thickness*stepping + ) + + def draw_tiles(self, spacing, x, y, dim, stepping): + offset = stepping*spacing/2 + edge = stepping*(1-spacing) + x_center = x+dim/2 + y_center = y+dim/2 + + colors = { + "white": "#fff", + "black": "#000", + "red": "#f00", + "green": "#0f0", + "blue": "#00f", + "yellow": "#ff0", + "cyan": "#0ff", + "magenta": "#f0f", + "orange": "#f50" + } + if self.direction_colored: + (up, down, left, right) = self.direction_colors + else: + (up, down, left, right) = [self.color_neutral] * 4 + triag_color = colors[self.triag_color] + + for tile in self.tiles: + black = tile.coord_black + white = tile.coord_white + + b_corner_x = (x_center + black[0]*stepping) + offset + b_corner_y = (y_center + black[1]*stepping) + offset + w_corner_x = (x_center + white[0]*stepping) + offset + w_corner_y = (y_center + white[1]*stepping) + offset + fill_corner_x = (x_center + (black[0] + white[0])/2 * stepping) + offset + fill_corner_y = (y_center + (black[1] + white[1])/2 * stepping) + offset + + triag_radius = 0.35*edge + triag_center_x = fill_corner_x + edge/2 + triag_center_y = fill_corner_y + edge/2 + triag_offset_height = 0.5*triag_radius + triag_offset_width = 1.732050580/2*triag_radius + + x_peak = triag_center_x + y_peak = triag_center_y + x_left = triag_center_x + y_left = triag_center_y + x_right = triag_center_x + y_right = triag_center_y + direction = tile.direction + if direction == (1, 0): + x_peak += triag_radius + x_left -= triag_offset_height + x_right -= triag_offset_height + y_left -= triag_offset_width + y_right += triag_offset_width + color = right + elif direction == (0, 1): + x_left += triag_offset_width + x_right -= triag_offset_width + y_peak += triag_radius + y_left -= triag_offset_height + y_right -= triag_offset_height + color = down + elif direction == (-1, 0): + x_peak -= triag_radius + x_left += triag_offset_height + x_right += triag_offset_height + y_left -= triag_offset_width + y_right += triag_offset_width + color = left + elif direction == (0, -1): + x_left += triag_offset_width + x_right -= triag_offset_width + y_peak -= triag_radius + y_left += triag_offset_height + y_right += triag_offset_height + color = up + + self.canvas.create_rectangle( + b_corner_x, + b_corner_y, + b_corner_x + edge, + b_corner_y + edge, + outline=colors[color], + fill=colors[color] + ) + self.canvas.create_rectangle( + w_corner_x, + w_corner_y, + w_corner_x + edge, + w_corner_y + edge, + outline=colors[color], + fill=colors[color] + ) + self.canvas.create_rectangle( + fill_corner_x, + fill_corner_y, + fill_corner_x + edge, + fill_corner_y + edge, + outline=colors[color], + fill=colors[color] + ) + if self.black: + self.canvas.create_polygon( + x_peak, + y_peak, + x_left, + y_left, + x_right, + y_right, + outline=triag_color, + fill=triag_color + ) \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..3a44d36 --- /dev/null +++ b/main.py @@ -0,0 +1,19 @@ +from aztecDiamond import AztecDiamond +from resizeTracker import ResizeTracker +from menuBar import MenuBar +from tkinter import Tk + +def main(): + x = 10005 + y = 600 + root = Tk() + ad = AztecDiamond(x, y) + tracker = ResizeTracker(ad) + root.geometry(str(x)+"x"+str(y)+"+300+300") + + menubar = MenuBar(root, ad) + + root.mainloop() + +if __name__ == '__main__': + main() diff --git a/menuBar.py b/menuBar.py new file mode 100644 index 0000000..b02416b --- /dev/null +++ b/menuBar.py @@ -0,0 +1,29 @@ +from tkinter import Menu + +class MenuBar(Menu): + + def __init__(self, root, aztecDiamond): + super().__init__(root) + self.aztecDiamond = aztecDiamond + root.config(menu=self) + + self.growLock = False + + self.add_command(label="Grow", command=self.growDiamond) + self.add_command(label="Color", command=self.toggleColor) + self.add_command(label="NoBlack", command=self.toggleBlack) + + def growDiamond(self): + if ~self.growLock: + self.growLock = ~self.growLock + self.aztecDiamond.grow_and_draw() + self.aztecDiamond.update() + self.growLock = ~self.growLock + + def toggleColor(self): + self.aztecDiamond.direction_colored = not self.aztecDiamond.direction_colored + self.aztecDiamond.place() + + def toggleBlack(self): + self.aztecDiamond.black = not self.aztecDiamond.black + self.aztecDiamond.place() \ No newline at end of file diff --git a/resizeTracker.py b/resizeTracker.py new file mode 100644 index 0000000..d440a92 --- /dev/null +++ b/resizeTracker.py @@ -0,0 +1,15 @@ +class ResizeTracker: + + def __init__(self, frame): + self.frame = frame + self.width = frame.winfo_width() + self.height = frame.winfo_height() + frame.bind("", self.resize) + + def resize(self, event): + if (event.widget == self.frame) and (self.width != event.width or self.height != event.height): + self.width = event.width + self.height = event.height + self.frame.dimensions = (self.width, self.height) + self.frame.initialize_draw_constants() + self.frame.place() \ No newline at end of file diff --git a/tile.py b/tile.py new file mode 100644 index 0000000..82fc296 --- /dev/null +++ b/tile.py @@ -0,0 +1,15 @@ +from tuple_addition import tuple_add as tAdd + +class Tile: + + def __init__(self, coord_black, coord_white, direction): + self.coord_black = coord_black + self.coord_white = coord_white + self.direction = direction + + def shift(self): + self.coord_black = tAdd(self.coord_black, self.direction) + self.coord_white = tAdd(self.coord_white, self.direction) + return (self.coord_black, self.coord_white) + + \ No newline at end of file diff --git a/tuple_addition.py b/tuple_addition.py new file mode 100644 index 0000000..23cce9e --- /dev/null +++ b/tuple_addition.py @@ -0,0 +1,8 @@ +def tuple_add(t1, t2): + n = len(t1) + if n != len(t2): + raise TypeError() + ret = [] + for i in range(n): + ret.append(t1[i] + t2[i]) + return tuple(ret) \ No newline at end of file